26.3 执行上下文
每个线程都关联了一个上下文数据结构。执行上下文(execution context)包括的东西有安全设置、宿主设置以及逻辑调用上下文数据。
理想情况下,每当一个线程(初始线程)使用另一个线程(辅助线程)执行任务时,前者的执行上下文应该流向(复制到)辅助线程。这就确保了辅助线程执行的任何操作使用的是相同的安全设置和宿主设置。还确保了初始线程的逻辑调用上下文可以在辅助线程中使用。
System.Threading命名空间有一个ExecutionContext类,它允许你控制线程的执行上下文如何从一个线程“流”向另一个。
只有在辅助线程不需要或者不访问上下文信息时,才应阻止上下文的流动。如果初始线程的执行上下文不流向辅助线程,辅助线程会使用和它关联的任何执行上下文。这种情况下,辅助线程不会执行要依赖于执行上下文状态(比如用户的Windows身份)的代码。
using System;
using System.Runtime.Remoting.Messaging;
using System.Threading;
namespace ThreadStudy
{
class Program
{
static void Main(string[] args)
{
//将一些数据放到Main线程的逻辑调用上下文中
CallContext.LogicalSetData("Name", "Anders");
//初始化要由一个线程池线程做的一些工作
//线程池线程能访问逻辑调用上下文数据
ThreadPool.QueueUserWorkItem(Print);
Console.WriteLine("Main thread:Executing...");
Thread.Sleep(1000);
//现在阻止Main线程的执行上下文的流动
ExecutionContext.SuppressFlow();
//初始化要由一个线程池线程做的一些工作
//线程池线程不能访问逻辑调用上下文数据
ThreadPool.QueueUserWorkItem(Print);
ExecutionContext.RestoreFlow();
Thread.Sleep(1000);
Console.WriteLine("Main thread:Execute completely...");
}
static void Print(object seconds)
{
Console.WriteLine("Here is thread1...");
Console.WriteLine("The name is {0}...", CallContext.LogicalGetData("Name"));
}
}
}
Main thread:Executing...
Here is thread1...
The name is Anders...
Here is thread1...
The name is ...
Main thread:Execute completely...
Press any key to continue . . .
虽然我们讨论的是调用ThreadPool.QueueUserWorkflowItem时阻止执行上下文的流动,但在使用Task对象时,以及在发起异步I/O操作时,这个技术同样有用。