线程也疯狂------计算限制的异步操做

前言

异步的限制操做主要做用于其余执行线程,例如规则检查、音频或视频数据转码以及生成图形略缩图,在金融和建筑工程应用程序中,计算限制的操做也是十分广泛的。编程

 

CLR线程池

线程池是你的应用程序能使用的线程的一个集合,每一个线程池都是由CLR控制的全部AppDomain共享,若是一个进程加载了多个CLR,那么每一个CLR都有它本身的线程池,CLR初始化时,线程池中原本没有线程,线程池的内部维护了一个队列请求,应用程序执行一个异步时,就调用某个方法,将一个记录项追加到线程池的队列中,线程池的代码从这个队列中提取记录项,将这个记录项派发给一个线程池线程,若是线程池中没有线程就建立新的线程,当任务执行后,线程并不会销毁,返回线程池,进入空闲状态,等待响应另外一个请求,再也不消耗额外的性能。安全

可是当一个线程闲着没事儿一段时间后,线程会自动释放资源,使用线程池的目的就是不用担忧线程建立和销毁带来的性能损失。服务器

 

简单的计算限制操做

ThreadPool类定义的一个方法:数据结构

static Boolean QueueUserWorkItem(WaitCallback callBack,object obj);异步

方法说明:向线程池中添加一个工做项以及可选的状态数据,而后执行此工做项,可向方法传递一个obj参数异步编程

代码演示函数

 1 class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Console.WriteLine("程序开始执行");
 6             ThreadPool.QueueUserWorkItem(ComputerSort, 6);
 7             Console.WriteLine("模拟其余操做执行5s");
 8             Thread.Sleep(5000);
 9             Console.WriteLine("点击Enter退出程序");
10             Console.ReadLine();
11         }
12 
13         private static void ComputerSort(object obj)
14         {
15             Console.WriteLine("线程池开始执行 参数={0}",obj.ToString());
16         }
17     }

显示结果性能

咱们发现输出的执行顺序会发生变化,是由于两个方法相互之间在异步上运行的,Windwos调度器决定具体先调度那个线程,若是是多核CPU可能同时调度它们。spa

执行上下文

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

理想状况下,每当一个线程使用另外一个线程(辅助线程)执行任务时,前者的执行上下文应该流向后者,确保辅助线程执行的操做都是使用的相同安全设置和宿主设置。

经过阻止执行上下文流动能够提高应用程序的性能,尤为是服务器应用性能提升显著,客户端的效果通常。

事例代码:

 

 1  static void Main(string[] args)
 2         {
 3 
 4             //将数据放入Main线程的逻辑上下文中
 5             CallContext.LogicalSetData("Name","Tom");
 6 
 7             ThreadPool.QueueUserWorkItem(p =>
 8             {
 9                 Console.WriteLine("Name = {0}",CallContext.LogicalGetData("Name"));
10             });
11 
12             ExecutionContext.SuppressFlow();
13 
14             ThreadPool.QueueUserWorkItem(p =>
15             {
16                 Console.WriteLine("Name = {0}", CallContext.LogicalGetData("Name"));
17             });
18 
19             ExecutionContext.RestoreFlow();
20 
21             ThreadPool.QueueUserWorkItem(p =>
22             {
23                 Console.WriteLine("Name = {0}", CallContext.LogicalGetData("Name"));
24             });
25 
26             Console.ReadLine();
27 
28         }

 

协做式取消和超时

对于长时间运行的计算限制操做,支持取消是一个必要的操做,.Net提供了标准的取消操做模式,不管执行操做的代码,仍是试图取消操做的代码,都必须使用下面介绍的类型。

System.Threading.CancellationTokenSource------->这个对象包含了管理取消有关的全部状态,能够从它的Token属性得到一个或者多个CancellationToken实例,

 1  static void Main(string[] args)
 2         {
 3             CancellationTokenSource  cts = new CancellationTokenSource();
 4 
 5             ThreadPool.QueueUserWorkItem(state => Count(cts.Token, 100));
 6 
 7             Console.WriteLine("输入Enter中止计算");
 8 
 9             Console.ReadLine();
10 
11             cts.Cancel();
12 
13             Console.ReadLine();
14         }
15 
16         private static void Count(CancellationToken token,int count)
17         {
18             for (int i = 0; i <=count; i++)
19             {
20                 if (token.IsCancellationRequested)
21                 {
22                     Console.WriteLine("接收到取消信号");
23                     break;
24                 }
25                 Console.WriteLine("i = {0}",i);
26                 Thread.Sleep(1000);
27             }
28         }

若是愿意可调用CancellationTokenSource的Register方法登记一个或者多个在取消一个CancellationTokenSource时调用的方法,要向方法传递一个Action<object>委托,一个要经过委托方法传给回调,以及一个Boolean值,该值指明是否要使用调用线程的SynchroinzationContent来调用委托。

 

1  cts.Token.Register(() =>
2             {
3                 Console.WriteLine("接收到取消信号后,开始调用回调函数");
4             });

 

 在不少状况下,咱们须要在过一段时间以后才取消操做,例如服务器应用程序可能会根据客户端的请求进行计算,但必须在两秒内响应,不管是否完成必须结束这次会话。在.NET 4.5中,CacncellationTokenSource提送了一个CancelAfter的方法

1  public void CancelAfter(int millisecondsDelay)

 

本章节的内容就讲解到这里,下节咱们将会继续 线程也疯狂-----异步编程。

相关文章
相关标签/搜索