十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
阅读本篇前,读者需对.NET4 System.Threading.Tasks 以及 Task Schedulers 有一定的了解。如果不是很了解,请查阅以下相关信息:

创新互联拥有10多年成都网站建设工作经验,为各大企业提供网站设计制作、做网站服务,对于网页设计、PC网站建设(电脑版网站建设)、重庆APP软件开发、wap网站建设(手机版网站建设)、程序开发、网站优化(SEO优化)、微网站、申请域名等,凭借多年来在互联网的打拼,我们在互联网网站建设行业积累了很多网站制作、网站设计、网络营销经验,集策划、开发、设计、营销、管理等网站化运作于一体,具备承接各种规模类型的网站建设项目的能力。
Task: http://msdn.microsoft.com/en-us/library/system.threading.tasks.task%28VS.100%29.aspx
Task Schedulers: http://msdn.microsoft.com/en-us/library/dd997402.aspx
首先回顾相关场景:最近工作需要一直在.NET4下编写window service。在WindowsService下使用了多线程相关技术。期间就用了到了线程池。使用线程池的目的:在系统中进行多线程并发也担心并发数量太大影响性能。于是使用线程池进行排队。一批一批执行多线程。当我在使用传统的.NET线程池的过程中碰见了一些问题,请看以下代码:
- try
 - {
 - ThreadPool.SetMaxThreads(2, 2);
 - for (int i = 0; i < 5; i++)
 - {
 - ThreadPool.QueueUserWorkItem(new WaitCallback(InvokeThread1), i);
 - }
 - }
 - catch
 - {
 - Console.WriteLine("error");
 - }
 
这里建立一个同时2个线程并发的线程池。在上述代码第7行传入InvokeThread1方法:
- static void InvokeThread1(object obj) {
 - throw new NullReferenceException();
 - }
 
假设程序发生异常,这个异常却让整个程线程池序崩溃了。主程序并未catch到这个exception。也许您会说这本来就是这样的嘛,有什么好贴出来的。但是在.NET4中我们可以避免掉这个问题。(此时体现出.NET4的异常强大)。还有个问题有必要提到:如果一次有两个线程同时并发(一共要执行5个线程,每次并发2个)。假设其中一个线程执行过程中出现了异常,要让这两个线程以外的三个线程都停止运行,来节省系统资源。传统的线程池也许可以做到,但是控制起来估计不会让你太轻松。但是在.NET4的Task机制中,这些都得到了妥善的解决,现将以上两个问题解决方案给出。如果存在不足的地方,请您指出。
一、自定义TaskScheduler
TaskScheduler代码如下:
自定义TaskScheduler
- //自定义TaskScheduler
 - public class CustomTaskScheduler : TaskScheduler, IDisposable
 - {
 - //调用Task的线程
 - Thread[] _Threads;
 - //Task Collection
 - BlockingCollection
 _Tasks = new BlockingCollection (); - int _ConcurrencyLevel;
 - //设置schedule并发
 - public CustomTaskScheduler(int concurrencyLevel)
 - {
 - _Threads = new Thread[concurrencyLevel];
 - this._ConcurrencyLevel = concurrencyLevel;
 - for (int i = 0; i < concurrencyLevel; i++)
 - {
 - _Threads[i] = new Thread(() =>
 - {
 - foreach (Task task in _Tasks.GetConsumingEnumerable())
 - this.TryExecuteTask(task);27
 - });
 - _Threads[i].Start();
 - }
 - }
 - protected override void QueueTask(Task task)
 - {
 - _Tasks.Add(task);
 - }
 - protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued)
 - {
 - if (_Threads.Contains(Thread.CurrentThread)) return TryExecuteTask(task);
 - return false;
 - }
 - public override int MaximumConcurrencyLevel50 {
 - get
 - {
 - return _ConcurrencyLevel;54 }
 - }
 - protected override IEnumerable
 GetScheduledTasks() - {
 - return _Tasks.ToArray();
 - }
 - public void Dispose()
 - {
 - this._Tasks.CompleteAdding();
 - foreach (Thread t in _Threads)
 - {
 - t.Join();
 - }
 - }
 - }
 
该scheduler代码很简单,重写相关System.Threading.Tasks.TaskScheduler类下的相关方法即可,代码中已给出相关注释。
二、使用自定义的TaskScheduler
调用TaskScheduler代码:
- List
 listMsg = new List () { "Task1", "Task2", "Task3", "Task4", "Task5", "Task6" }; - List
 listTask = new List (); - foreach (string msg in listMsg)
 - {
 - Task myTask = new Task(obj => InvokeThread2((string)obj), msg, token);
 - listTask.Add(myTask);
 - myTask.Start(customTaskScheduler);
 - }
 - try
 - {
 - //等待所有线程全部运行结束
 - Task.WaitAll(listTask.ToArray());
 - }
 - catch (AggregateException ex)
 - {
 - //.NET4 Task的统一异常处理机制
 - foreach (Exception inner in ex.InnerExceptions)
 - {
 - Console.WriteLine("Exception type {0} from {1}",
 - inner.GetType(), inner.Source);
 - }
 - }
 - Console.ReadLine();
 
InvokeThread2 相关代码:
- static void InvokeThread2(string msg)
 - {
 - try
 - {
 - var x = Convert.ToInt32(msg.Replace("Task", "").Trim());
 - Console.WriteLine(msg);
 - Thread.Sleep(1000 * 5);
 - Console.WriteLine("{0} ok", msg); }
 - catch (Exception ex)
 - {
 - //如果有异常发生则取消正在排队的所有线程。
 - tokenSource.Cancel();
 - Exception exception = new Exception("error");
 - exception.Source = msg;
 - throw exception;
 - } }
 
以上代码运行效果如下:
接着在TaskScheduler调用代码中如果将第一行代码listMsg值修改成 List
这个运行结果重点要强调的地方为:后面这7个exception。聪明的您或许已经看出来前6个exception属于没有执行的"Task4", "Task5", "Task6", "Task7", "Task8", "Task9",而最后一个exception才是真正的发生异常的"TaskA"。这里主要用到了Task的统一异常处理机制AggregateException。可以从运行结果得到:Task1,Task2,Task3执行成功了,但是TaskA发生了异常导致了后面排队的"Task4", "Task5", "Task6", "Task7", "Task8", "Task9"都不会执行了。节省了系统资源,同时也提高了系统性能。
三、小结
本文主要用到了的是.NET4 的Task相关技术,Task让我们在多核并行控制的时候更加简单,功能更加强大。如果需进一步了解相关技术,博客园已经有不少教程。微软的MSDN也提供了很多参考资料。 最后希望本文可以给您的开发带来帮助。
原文链接:http://www.cnblogs.com/ryanding/archive/2011/03/22/1990799.html
【编辑推荐】