(CLR via C#学习笔记)异步操作 - 线程池
一 线程池基础
1.线程池维护了一个操作请求队列,将请求的操作追加到线程池队列中,线程池的代码从队列中提取
操作项,派发给线程池中的线程;
2.CLR初始化时,线程池中是没有线程的,当有操作派发给线程池时,如果线程池中没有线程或者没有
空闲状态的线程,将会创建一个新的线程执行派发的操作,如果有空闲状态的线程,将直接派发一个
空闲状态的线程执行操作;
3.线程池线程完成操作任务后,线程不会被销毁,而是返回线程池,进入空闲状态,等待响应另一个派发请求;
4.当一个线程池线程处于空闲状态一段时间后(不同的CLR对这个时间定义不同),线程会自己醒来终止自己以释放内存资源.
示例代码:
1 Console.WriteLine("主线程..."); 2 ThreadPool.QueueUserWorkItem(DoSomething, 5); 3 Console.WriteLine("主线程继续执行..."); 4 5 static void DoSomething(object state) 6 { 7 Thread.Sleep(2000); 8 int num = (int)state; 9 Console.WriteLine("DoSomething..., Number:" + num); 10 return; 11 }
输出结果:
主线程...
主线程继续执行...
DoSomething..., Number:5
二 执行上下文
System.Threading命名空间有一个ExecutionContext类,它允许你控制线程的执行上下文如何
从一个线程"流"向另一个,默认情况下,CLR自动造成初始线程的志向上下文"流向"任何辅助线程.
示例代码:
1 CallContext.LogicalSetData("Name", "Mike"); 2 //线程池线程可以访问逻辑调用上下文数据 3 ThreadPool.QueueUserWorkItem(state => Console.WriteLine("Name:{0}", CallContext.LogicalGetData("Name"))); 4 5 //取消执行上下文在异步线程间的流动 6 ExecutionContext.SuppressFlow(); 7 //线程池线程将不能访问逻辑调用上下文数据 8 ThreadPool.QueueUserWorkItem(state => Console.WriteLine("Name:{0}", CallContext.LogicalGetData("Name"))); 9 10 //恢复执行上下文在异步线程间的流动 11 ExecutionContext.RestoreFlow(); 12 //...
执行结果:
Name:Mike
Name:
三 协作式取消
1 //注册取消CancelationToken时调用的委托 2 var cts = new CancellationTokenSource(); 3 cts.Token.Register(() => Console.WriteLine("The operation will be cancelled. -- 1")); 4 cts.Token.Register(() => Console.WriteLine("The operation will be cancelled. -- 2")); 5 6 //线程开始执行操作 7 ThreadPool.QueueUserWorkItem(a => Count(cts.Token, 1000)); 8 9 Console.WriteLine("Please <Enter> to cancel the operation."); 10 Console.ReadLine(); 11 12 //传达取消请求 13 cts.Cancel(); 14 15 16 //执行计数操作 17 static void Count(CancellationToken token, int countTo) 18 { 19 for (int i = 0; i < countTo; i++) 20 { 21 if (token.IsCancellationRequested) //是否已请求取消 22 { 23 break; 24 } 25 Thread.Sleep(500); 26 Console.WriteLine(i); 27 } 28 }
说明: 键入"Enter"键,传达取消标识,Count计数操作结束,注册的两个委托方法得到执行.