CLR线程
CLR使用的是Windows的线程处理能力,目前的CLR实现一个CLR线程对应于一个Windows线程
System.Threading.Thread
System.Threading.Thread t = new System.Threading.Thread(op =>
{
Console.WriteLine(op);
});
t.Start("demo");
t.Join();
CLR线程池
创建和销毁线程是一个昂贵的操作,要耗费大量时间、资源,对性能也有影响。为改善这个情况,CLR包含了代码来管理它的线程池。可将线程池想象成可由你的程序使用的一个线程集合,每个CLR一个线程池,这个线程池可由CLR控制的所有AppDomian共享。如果一个进程加载了多个CLR,每个CLR都有自己的线程池。
System.Threading.ThreadPool.QueueUserWorkItem(op =>
{
Console.WriteLine(op);
},
"demo");
执行上下文
每个线程都关联一个执行上下文结构,包括:安全设置(Thread.Principal Windows身份)、宿主设置(System.Threading.HostExecutionContextManager)、逻辑调用上下文数据(System.Runtime.Remoting.Messaging.CallContext的LogicSetData和LogicGetData)
默认情况下,CLR自动造成初始线程的执行上下文复制到任何辅助线程,如果需要控制上下文的复制问题,可使用System.Threading.ExecutionContext类,如:
// Put some data into the Main thread’s logical call context
CallContext.LogicalSetData("Name", "Jeffrey");
// Initiate some work to be done by a thread pool thread
// The thread pool thread can access the logical call context data
ThreadPool.QueueUserWorkItem(
state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));
// Suppress the flowing of the Main thread’s execution context
ExecutionContext.SuppressFlow();
// Initiate some work to be done by a thread pool thread
// The thread pool thread can NOT access the logical call context data
ThreadPool.QueueUserWorkItem(
state => Console.WriteLine("Name={0}", CallContext.LogicalGetData("Name")));
// Restore the flowing of the Main thread’s execution context in case
// it employs more thread pool threads in the future
ExecutionContext.RestoreFlow();
协作式取消
.net提供了标准的取消操作模式
private static void CancellingAWorkItem() {
CancellationTokenSource cts = new CancellationTokenSource();
// Pass the CancellationToken and the number-to-count-to into the operation
ThreadPool.QueueUserWorkItem(o => Count(cts.Token, 1000));
Console.WriteLine("Press <Enter> to cancel the operation.");
Console.ReadLine();
cts.Cancel(); // If Count returned already, Cancel has no effect on it
// Cancel returns immediately, and the method continues running here...
Console.ReadLine(); // For testing purposes
}
private static void Count(CancellationToken token, Int32 countTo) {
for (Int32 count = 0; count < countTo; count++) {
if (token.IsCancellationRequested) {
Console.WriteLine("Count is cancelled");
break; // Exit the loop to stop the operation
}
Console.WriteLine(count);
Thread.Sleep(200); // For demo, waste some time
}
Console.WriteLine("Count is done");
}
任务
ThreadPool.QueueUserWorkItem虽然简单,担忧如下限制:
Ø 没有内建的机制知道操作什么时候完成
Ø 没有内建的机制在操作完成时获得一个返回值
System.Threading.Tasks下的类型可解决这个问题
Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 10000);
// You can start the task sometime later
t.Start();
// Optionally, you can explicitly wait for the task to complete
t.Wait(); // FYI: Overloads exist accepting a timeout/CancellationToken
// Get the result (the Result property internally calls Wait)
Console.WriteLine("The sum is: " + t.Result); // An Int32 value
任务的取消使用“协作式取消”方式,CancellationTokenSource
一个任务完成时自动启动另一个新任务
Task.ContinueWith
任务可以启动子任务
任务工厂
有时,可能需要创建一组Task对象来共享相同的状态,为了避免机械的将相同的参数传给每个Task的构造器,可以创建一个任务工厂来封装通用的状态。
参考
Clr Via C# 25 26章