C#学习笔记13

时间:2022-01-16 06:04:37

1.Task概述:Task是对操作系统线程的抽象,目的是使线程池能高效地管理线程的分配和回收,Task使用的底层线程属于一种共享资源,任务需要互相协作,并及时归还线程,以便用相同的共享资源(线程)满足其他请求。

2.Task.AsyncState:获取在创建 Task 时提供的状态对象,如果未提供,则为 null。若状态对象在task内部改变了,AsyncState的数据也是改变后的状态对象。可查看ThreadApply.TaskAsyncState()方法的代码。

3.Task.ContinueWith():它的作用是把任务链接起来,在父任务完成后会立即执行后续任务。若在父任务的实例上多次调用ContinueWith()方法,在父任务完成后,所添加的后续任务会并行执行。当然可以根据TaskContinuationOptions枚举来指定根据父任务的执行情况,来执行后续任务。

4.Task的异常:Task执行期间产生的未处理的异常后会被禁止,直到调用某个任务完成(Task)成员,如Wait()、Result、WaitAll()、WaitAny(),上述的成员都会引发在任务执行期间发生的未处理异常。可查看代码TreadApply.TaskException()。

5.Task的异常2:要在不使用try/catch块的情况下处理未处理的异常,另一个办法是使用ContinueWith()任务,利用ContinueWith()委托的task参数,可以评估父任务的Exception属性,可查看代码TreadApply.TaskException2()。

6.Task的取消:可查看代码ThreadApply.TaskCancellationToken()方法,需要用到CancellationTokenSource类,对CancellationTokenSource.Cancel()方法的调用,会在从CancellationTokenSource.Token复制的所有取消标志上设置IsCancellationRequested属性。此中需要注意的2点,

(1)取消标志:CancellationToken(而不是CancellationTokenSource)会在异步任务中求值,CancellationToken看起来和CancellationTokenSource差不多。但CancellationToken用于监视和响应一个取消请求,而CancellationTokenSource用于取消任务本身。

(2)复制的:CancellationToken 是一个struct,所以调用CancellationTokenSource.Token会创建标志的一个副本,这样一来所有取消标志的实例都是线程安全的。

7.长时间运行的任务:如果开发人员知道一个Task要长时间运行,会长时间“霸占”一个底层线程资源,开发人员应告诉线程池共享线程不会太快交还。这样一来,线程池更有可能为任务创建一个专用线程(而不是分配其中的一个共享线程),为此,在调用StartNew()时,要使用TaskCreationOption.LongRunning选项。 

8.并行迭代:.net4.0中新增了2个并行迭代,分别为Parallel.For()与Parallel.Foreach()。API会判断同时执行多少个线程才是效率最高的,可查看ThreadApply.ParallelFor()与ThreadApply.ParallelForeach()方法的代码。

9.并行异常的处理:在并行处理时,在并行的内容中可能出现多个异常,那么其异常信息会归到AggregateException异常类型,它是包含了多个内部异常的一个异常。System.Threading.Task命名空间一致使用System.AggregateException对未处理的异常进行分组,因为对于并行操作,经常都可能产生多个异常。如ThreadApply.ParallelForeach()代码清单。

10.并行循环的取消:Task需要一个显式调用才能阻塞(它的调用线程,并一直等)到它完成,并行循环虽然和任务不同,它以并行方式执行迭代,但它仍会阻塞(它的调用线程,并一直等)到整个Parallel.For()或Parallel.ForEach()循环结束。所以为了取消并行循环,调用取消请求的那个线程通常不能是正在执行并行循环的那个线程。如代码ThreadApply.CancelParallelForeach()清单。

11.并行迭代的中断:和标准的for循环相似,Parallel的循环也支持中断(ParallelLoopState.Break())以退出循环并取消进一步迭代的概念。但是,在并行执行的上下文中,中断循环意味着中断迭代之后的新迭代不应开始,当前正在执行的迭代还是会继续运行直至完成的。要想知道执行了一次中断的最低的迭代,并了解中断是否阻止了一个或多个迭代启动,可查看并行For()/ForEach()方法返回的ParallelLoopResult对象(其含有IsCompleted、LowestBreakIteration属性)。

12.并行Linq查询:并行Linq的功能都在System.Linq.ParallelEnumerable类中,,该类的方法形式与System.Linq.Enumerable类的方法形式基本一致,ParallelEnumerable类中有对IEnumerable<T>类型,进行转化为并行的处理类型的扩展方法,即IEnumerable<T>.AsParallel()。只有在执行此转化后,才能对集合进行并行处理。

13.并行Linq的异常:与并行For和Foreach一样,PLinq运算也可能因为完全相同的原因返回多个异常(不同的迭代同时执行),幸好,捕获异常的机制也是一样。PLinq异常可以通过AggregateException的InnerException属性来访问,因此,将一个Plinq查询包装到一个try/catch块中,并捕捉AggregateException类型的异常,就可以处理每一次迭代中的未处理异常。