在.NET中,每个线程都关联了一个执行上下文的数据结构,执行上下文 包含安全设置(压缩栈、Thread 的 Principal 属性和 Windows 身份)、宿主设置以及逻辑调用上下文数据,线程在执行它的代码的时候,一些操作会受到线程执行上下文(尤其时安全设置)的影响(例如:上下文中的 Windows 身份会影响文件读写的权限)。
理想情况下,每当一个线程(初始线程)使用另一个线程(辅助线程)执行任务的时候,初始线程的执行上下文会流向(复制到)辅助线程,这确保了辅助线程执行的任何操作使用的是安全设置相同的安全设置和宿主设置,还确保了存储在初始线程逻辑调用上下文数据中的数据可以在辅助线程中读取(注意,流向辅助线程的上下文对象,是初始线程上下文对象的一个副本,辅助线程对上下文对象的修改,不会影响到初始线程的上下文对象)。
以下代码演示了这一现象:
CallContext.LogicalSetData("Name", "WLJ");
ThreadPool.QueueUserWorkItem((state) =>
{
String value = CallContext.LogicalGetData("Name").ToString();
Console.WriteLine(value);
CallContext.LogicalSetData("Name", "WLJNew");
});
Thread.Sleep(1000);
Console.WriteLine(CallContext.LogicalGetData("Name"));
//最后输出结果都是 WLJ
默认情况下,CLR会自动将初始线程的执行上下文流向任何辅助线程,而执行上下文对象中包含了大量信息,收集并复制执行上下文对象需要不少的时间,而且如果辅助线程又使用了辅助线程,则它的执行上下文信息又会流向其辅助线程。
当然我们可以阻止线程执行上下文的流动,以提升程序的性能,这对于经常使用辅助线程帮助完成任务,而又不需要访问线程执行上下文信息的程序提升是较大的。可以使用以下代码阻止执行上下文的流动:
ExecutionContext.SuppressFlow(); // 该类位于System.Threading 名空间中
恢复执行上下文的流动:
ExecutionContext.RestoreFlow();
如果阻止了执行上下文的流动,辅助线程会使用上一次和它关联的任意执行上下文。