Home Random Page


CATEGORIES:

BiologyChemistryConstructionCultureEcologyEconomyElectronicsFinanceGeographyHistoryInformaticsLawMathematicsMechanicsMedicineOtherPedagogyPhilosophyPhysicsPolicyPsychologySociologySportTourism






Nbsp;   Execution Contexts

Every thread has an execution context data structure associated with it. The execution context includes things such as security settings (compressed stack, Thread’s Principal property, and Windows identity), host settings (see System.Threading.HostExecutionContextManager), and logical call context data (see System.Runtime.Remoting.Messaging.CallContext’s Logical­ SetData and LogicalGetData methods). When a thread executes code, some operations are affected by the values of the thread’s execution context settings. This is certainly true for the security settings. Ideally, whenever a thread uses another (helper) thread to perform tasks, the issuing thread’s execution context should flow (be copied) to the helper thread. This ensures that any operations performed by helper thread(s) are executing with the same security settings and host settings. It also


ensures that any data stored in the initiating thread’s logical call context is available to the helper thread.

By default, the CLR automatically causes the initiating thread’s execution context to flow to any helper threads. This transfers context information to the helper thread, but it comes at a performance cost, because there is a lot of information in an execution context, and accumulating all of this infor- mation and then copying it for the helper thread takes a fair amount of time. If the helper thread then employs additional helper threads, then more execution context data structures have to be created and initialized as well.

In the System.Threading namespace, there is an ExecutionContext class that allows you to control how a thread’s execution context flows from one thread to another. Here is what the class looks like.

 

public sealed class ExecutionContext : IDisposable, ISerializable { [SecurityCritical] public static AsyncFlowControl SuppressFlow(); public static void RestoreFlow();

public static Boolean IsFlowSuppressed();

 

// Less commonly used methods are not shown

}

 

You can use this class to suppress the flowing of an execution context, thereby improving your

application’s performance. The performance gains can be quite substantial for a server application. There is not much performance benefit for a client application, and the SuppressFlow method is marked with the [SecurityCritical] attribute, making it impossible to call in some client applica- tions (like Microsoft Silverlight). Of course, you should suppress the flowing of execution context only if the helper thread does not need to access the context information. If the initiating thread’s execu- tion context does not flow to a helper thread, the helper thread will use whatever execution context it last associated with it. Therefore, the helper thread really shouldn’t execute any code that relies on the execution context state (such as a user’s Windows identity).

Here is an example showing how suppressing the flow of execution context affects data in a

thread’s logical call context when queuing a work item to the CLR’s thread pool.1



 

public static void Main() {

// 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")));

 

// Now, suppress the flowing of the Main thread's execution context ExecutionContext.SuppressFlow();

 

 
 

1 The items that you add to the logical call context must be serializable, as discussed in Chapter 24, “Runtime Serialization.” Flowing an execution context that contains logical call context data items can hurt performance dramatically, because capturing the execution context requires serializing and deserializing all the data items.


// Initiate some work to be done by a thread pool thread

// The thread pool thread CANNOT 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();

...

Console.ReadLine();

}

 

When I compile and run the preceding code, I get the following output.

 

Name=Jeffrey Name=

 

Although this discussion has focused on suppressing the flow of execution context when calling ThreadPool.QueueUserWorkItem, this technique is also useful when using Task objects (discussed in the “Tasks” section of this chapter) and is also useful when initiating asynchronous I/O operations (discussed in Chapter 28, “I/O-Bound Asynchronous Operations”).

 

 


Date: 2016-03-03; view: 732


<== previous page | next page ==>
Nbsp;   Performing a Simple Compute-Bound Operation | Nbsp;   Cooperative Cancellation and Timeout
doclecture.net - lectures - 2014-2024 year. Copyright infringement or personal data (0.008 sec.)