首页 > 代码库 > (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#学习笔记)任务和并行操作