需要说明的是,线程池会根据需要增加线程数量,线程池采用的是工作窃取队列,以尽可能的达到高效
异步编程
目前最常用的异步编程模型是TAB编程(基于任务的编程模式)。异步编程提高了响应能力,也实现了可扩展性。比较直观的是,大家在处理Winform的时候遇到过界面卡死的情况,异步编程可以在程序运行的过程中继续相应用户的输入,而不会导致界面卡死,并提高了提高服务器端应用的TPS(Transactions Per Second)和 QPS (Queries Per Second)。
.NET4.5以后为异步编程引入了async和await关键字,async关键字加在方法声明上,主要用来配合方法内的await关键字,这两个关键字的引入,使得C#在异步编程上更加优雅。如下所示
public async Task DelayAsync()
{
await Task.Delay(1000);
}
异步编程的执行流程一般是,当系统运行至await,会暂停,并可以捕捉到当前的上线文,SynchronizationContext,如果该上线文为空,就会使用当前的TaskScheduler,该方法也会在这个上线文中继续执行。代码执行完以后,会尝试在原始的上下文中恢复运行。
注意:运行winform和asp.net请求时会采用UI上下文或者asp.net上下文,其他情况下则采用线程池上下文。
异步方法的等待方式有await,Task.Wait和Task<T>.Result。但是要避免是用Task.Wait和Task<T>.Result,因为他们在UI线程或者ASP.NET线程环境中会导致死锁。这个地方需要说明一下死锁问题
public async Task DelayAsync()
{
await Task.Delay(1000);//捕捉当前上下文,并试图在已捕捉的上下文中继续运行
}
void Test()
{
Task task= DelayAsync();
Task.Wait();//同步程序块,正在等待异步方法完成=======阻塞线程
}
UI或者asp.net的上下文每次只能同时运行一个线程。Wait方法已经阻塞了一个线程,所以在await的时候无法捕捉上下文。可以使用ConfigureAwait方法,设置参数continueOnCapturedContext为false。由此,可以带来一个启示,就是在线程池线程上使用ConfigureAwait(false),在用户界面或接口代码中再恢复过来。










