第二十七章 计算限制的异步操做

目录算法

27.1 CLR线程池基础安全

27.2 执行简单的计算限制操做数据结构

27.3 执行上下文并发

27.4 协做式取消和超时异步

27.5 任务性能

27.6 Parallel的静态For,ForEach和Invoke方法spa

27.7 并行语言集成查询(PLINQ)线程

27.8 执行定时计算限制操做调试

27.9 线程池如何管理线程orm

异步执行计算限制操做,容许线程池在多个CPU内核上调度任务,使多个线程能并发工做,从而高效率地使用系统资源,同时提高应用程序的吞吐能力。

27.1 CLR线程池基础

线程池是你的应用程序能使用的线程集合。每CLR一个线程池:这个线程池由CLR控制的全部AppDomain共享。

CLR初始化时,线程池中是没有线程的。在内部,线程池维护了一个操做请求队列。应用程序执行一个异步操做时,就调用某个方法,将一个记录项追加到线程池队列中。线程池的代码从这个队列中提取记录项,将这个记录项派发给一个线程池线程。

27.2 执行简单的计算限制操做

将一个异步的计算限制操做放到线程池队列中:ThreadPool类

static Boolean QueueUserWorkItem(WaitCallback callback);

static Boolean QueueUserWorkItem(WaitCallback callback, Object state); 

27.3 执行上下文

每一个线程都关联了一个执行上下文数据结构。执行上下文包括的东西有安全设置(压缩栈,Thread的Principal属性和Winodws身份)、宿主设置以及逻辑调用上下文数据。

ExecutionContext类:

[SecurityCritical] public static AsyncFlowControl SuppressFlow();

public static void RestoreFlow();

public static Boolean IsFlowSuppressed();

27.4 协做式取消和超时

 Microsoft .NET Framework 提供了标准的取消操做模式。这个模式是协做式的,意味着要取消的操做必须显示支持取消。

System.Threading.CancellationTokenSoure包含了和管理取消有光的全部状态。

public struct CancellationToken:

CancellationToken 实例是轻量级值类型,包含单个私有字段,即对其CancellationToken的IsCancellationRequested属性,了解循环是否应该提早终止,从而终止计算限制的操做。

27.5 任务

System.Threading.Tasks命名空间

27.5.1 等待任务完成并获取结果

若是计算限制的任务抛出未处理的异常,异常会被“吞噬”并存储到一个集合中,而线程池线程能够返回到线程池中。调用Wait方法或者Result属性时,这些成员会抛出一个System.AggregateException对象

27.5.2 取消任务

可调用一个CancellationTokenSource取消Task。

27.5.3 任务完成时自动启动新任务

伸缩性好的软件不该该使线程阻塞

27.5.4 任务能够启动子任务

任务支持父/子关系。

27.5.5 任务内部揭秘

每一个Task对象都有一组字段,这些字段构成了任务的状态。其中包括一个Int32ID,表明Task执行状态的一个Int32,对父任务的引用,对Task建立时指定的TaskScheduler的引用,对回调方法的引用,对要传给回调方法的对象的引用,对ExecutionContext的引用以及对MenualResetEventSlim对象的引用。另外,每一个Task对象都有对根据须要建立的补充状态的引用。补充状态包含了一个CancellationToken,一个ContinueWithTask对象集合,为抛出未处理异常的子任务而准备的一个Task对象集合等。

首次构造Task对象时,它的状态时Created。之后,当任务启动时,它的状态变成WaitingToRun。Task实际在一个线程上运行时,它的状态变成Runing。任务中止运行,并等待它的任何子任务时,状态变成WaitingForChildrenToComplete。任务完成时进入如下状态之一:RanToCompletion(运行完成),Canceld(取消)或Faulted(出错)。

27.5.6 任务工厂

TaskFactory

27.5.7 任务调度器

TaskScheduler对象负责执行被调度的任务,同时向Visual Studio调试器公开任务信息。FCL提供了两个派生自TaskScheduler的类型:线程池任务调度器,和同步上下文任务调度器。任务调度器将任务调度给线程池的工做者线程。

27.6 Parallel的静态For,ForEach和Invoke方法

System.Threading.Tasks.Parallel:For,ForEach,Invoke

Parallel的全部方法都让调用线程参与处理。调用Parallel方法的前提是:工做项必须能并行执行。另外,要避免会修改任何共享数据的工做项,不然多个线程同时处理可能会损坏数据。

重载版本:

接受ParallelOptions对象:

CancellationToke:容许取消操做。

Int32MaxDegreeOfParallelism:容许指定能够并发操做的最大工做项目数。

TaskSchedulerTaskScheduler:容许指定要使用哪一个TaskScheduler。

任务局部初始化委托:为参与工做的每一个任务都调用一次该委托。这个委托是在任务别要求处理一个工做项以前调用的。

主体委托:为参与工做的各个线程所处理的每一项都调用一次该委托。

任务局部终结委托:为参与工做的每个任务都调用一次该委托。这个委托是在任务处理好派发给它的全部工做项以后调用。即便主体委托代码引起一个未处理的异常,也会调用它。

27.7 并行语言集成查询(PLINQ)

 使用LINQ to Objects时,只有一个线程顺序处理数据集合中的全部项:咱们称之为顺序查询。要提升处理性能,可使用并行LINQ(parallel LINQ),它将顺序查询转换成并行查询,在内部使用任务,将集合中的数据项的处理工做分散到多个CPU上,以便并发处理多个数据项。

AsParallel;AsSequential

27.8 执行定时计算限制操做

 System.Threading命名空间定义了一个Timer类,可用它让一个线程池线程定时调用一个方法。

System.Threading的Timer类:要在一个线程池线程上执行定时的(周期性发生的)后台任务,它是最好的计时器。

System.Windows.Forms的Timer类:构造这个类的实例,至关于告诉Windows将一个计时器和调用线程关联。

System.Windows.Threading的DispatcherTimer类:这个类是System.Windows.Forms的Timer类在Silverlight和WPF应用程序中的等价物。

Windows.UI.Xaml的DispatcherTimer类:这个类是System.Windows.Forms的Timer类在Windows Store应用中的等价物。

System.Timers的Timer类:这个计时器本质上是System.Threading的Timer类包装器。计时器到期(触发)会致使CLR将事件放到线程池队列中。(不建议使用)

27.9 线程池如何管理线程

27.9.1 设置线程池限制

CLR容许开发人员设置线程池要建立的最大线程数。但实践证实,线程池永远都不该该设置线程数上限,由于可能发生饥饿或死锁。

27.9.2 如何管理工做者线程

ThreadPool.QueueUserWorkItem方法和TImer类老是将工做项放到全局队列中。工做者线程采用一个先入先出(FIFO)算法将工做项从这个队列中取出,并处理它们。因为多个工做者线程可能同时从全局队列中拿走工做项,因此全部工做者线程都竞争一个线程同步锁,以保证两个或多个线程不会获取同一个工做项。

每一个工做者线程都有本身的本地队列。工做者线程调度一个Task时,该Task被添加到调用线程的本地队列。非工做者线程调度一个Task时,该Task被添加到全局队列。工做者线程采用后入先出(LIFO)算法将任务从本地队列中取出。因为工做者线程是惟一容许访问它本身的本地队列头的线程,因此无需同步锁,并且在队列中添加和删除Task的速度很是快,

相关文章
相关标签/搜索