首页 > 代码库 > (CLR via C#学习笔记)任务和并行操作
(CLR via C#学习笔记)任务和并行操作
一 任务
可以调用ThreadPool的QueueUserWorkItem方法发起一次异步的计算限制操作.
但这个技术有很多限制.最大的问题是没有内建的机制让你知道操作在什么时候
完成和操作完成时的返回值.为了克服这些限制(并解决其他一些问题),Microsoft
引入了任务的概念.
1 //调用QueueUserWorkItem 2 ThreadPool.QueueUserWorkItem(DoSomeThing, 5); 3 4 //用任务来做相同的事情 5 Task.Run(() => DoSomeThing(5));
二 任务抛出异常
如果计算限制的任务抛出未处理的异常,异常会被"吞噬"并存储到一个集合中,
而线程池线程可以返回到线程池中.调用Wait方法或者Result属性时,这些成员
会抛出一个System.AggregateException对象.
三 取消任务
调用CancellationToken的ThrowIfCancellationRequested,如果CancellationToken
已经取消,任务将会抛出OperationCanceledException.之所以选择抛出异常,是因为
和ThreadPool的QueueUserWorkItem方法初始化的工作项不同,任务有办法表示完成,
任务甚至能返回一个值.所以,采取一种方式将已完成的任务和出错的任务区分开.
而让任务抛出异常,就可以知道任务没有一直运行到结束.
1 CancellationTokenSource cts = new CancellationTokenSource(); 2 Task<int> t = Task.Run<int>(() => Sum(cts.Token, 2000)); 3 Thread.Sleep(10); 4 cts.Cancel(); 5 6 try 7 { 8 Console.WriteLine("The Sum is: " + t.Result); 9 } 10 catch (AggregateException x) 11 { 12 //将任何OperationCanceledException对象都视为已处理 13 //使其中只包含未处理的异常 14 x.Handle(e => e is OperationCanceledException); 15 16 //对未处理的异常进行处理 17 //TODO 18 //... 19 //... 20 21 Console.WriteLine("Sum was canceled"); 22 }
1 static int Sum(CancellationToken ct,int n) 2 { 3 if (n > 1000) 4 { 5 throw new Exception("Value of n is too large."); 6 } 7 8 int sum = 0; 9 for (int i = 1; i <= n; i++) 10 { 11 //如果CancellationTokenSource已取消(Cancel), 12 //下面代码将抛出"System.OperationCanceledException"异常 13 ct.ThrowIfCancellationRequested(); 14 sum += i; 15 } 16 return sum; 17 }
四 Parallel的静态For,ForEach和Invoke方法
使用Parallel的方法一些前提条件:
a.工作项必须能并行执行,如果工作必须顺序执行,就不要使用Paralle方法;
b.工作项最好不要有修改共享数据的操作,否则多个线程同时处理共享数据,可能会算坏
数据;
c.每个工作项都涉及大量工作,那么使用Parallel方法产生的性能损失可以忽略不计;
d.有大量可由多个线程同时处理的工作项,那么使用Parallel也许能获得性能的提升.
1 //Parallel的For方法 2 for (int i = 0; i < 1000; i++) 3 { 4 DoWork(i); 5 } 6 Parallel.For(0, 1000, i => DoWork(i)); 7 8 //Parallel的ForEach方法 9 int[] idCollection = new int[] {1,2,3,4,5,6,7,8,9 }; 10 foreach (var item in idCollection) 11 { 12 DoWork(item); 13 } 14 Parallel.ForEach(idCollection, item => DoWork(item)); 15 16 //Parallel的Invoke方法 17 Method1(); 18 Method2(); 19 Method3(); 20 Parallel.Invoke( 21 () => Method1(), 22 () => Method2(), 23 () => Method3());
五 定时计算限制操作(Timer)
FCL提供了几个以下几种主要的定时器:
a.System.Threading的Timer类
要在一个线程池上执行定时的(周期性发生的)后台任务,它是最好的计时器.
b.System.Timers的Timer类
这个计时器本质上是System.Threading的Timer类的包装类,它允许在Visual
Studio中的设计器更容易使用.
建议不用这个计时器,除非真的想在设计平面上添加一个计时器.
c.System.Windows.Forms的Timer类
(CLR via C#学习笔记)任务和并行操作