using System; using System.Threading; using System.Threading.Tasks;
classExample { static AsyncLocal<string> _asyncLocalString = new AsyncLocal<string>();
static ThreadLocal<string> _threadLocalString = new ThreadLocal<string>();
staticasync Task AsyncMethodA() { // Start multiple async method calls, with different AsyncLocal values. // We also set ThreadLocal values, to demonstrate how the two mechanisms differ. _asyncLocalString.Value = "Value 1"; _threadLocalString.Value = "Value 1"; var t1 = AsyncMethodB("Value 1");
staticasync Task AsyncMethodB(string expectedValue) { Console.WriteLine("Entering AsyncMethodB."); Console.WriteLine(" Expected '{0}', AsyncLocal value is '{1}', ThreadLocal value is '{2}'", expectedValue, _asyncLocalString.Value, _threadLocalString.Value); await Task.Delay(100); Console.WriteLine("Exiting AsyncMethodB."); Console.WriteLine(" Expected '{0}', got '{1}', ThreadLocal value is '{2}'", expectedValue, _asyncLocalString.Value, _threadLocalString.Value); }
staticasync Task Main(string[] args) { await AsyncMethodA(); } } // The example displays the following output: // Entering AsyncMethodB. // Expected 'Value 1', AsyncLocal value is 'Value 1', ThreadLocal value is 'Value 1' // Entering AsyncMethodB. // Expected 'Value 2', AsyncLocal value is 'Value 2', ThreadLocal value is 'Value 2' // Exiting AsyncMethodB. // Expected 'Value 2', got 'Value 2', ThreadLocal value is '' // Exiting AsyncMethodB. // Expected 'Value 1', got 'Value 1', ThreadLocal value is ''
using System; using System.Threading; using System.Threading.Tasks;
classThreadLocalDemo { // Demonstrates: // ThreadLocal(T) constructor // ThreadLocal(T).Value // One usage of ThreadLocal(T) staticvoidMain() { // Thread-Local variable that yields a name for a thread ThreadLocal<string> ThreadName = new ThreadLocal<string>(() => { return"Thread" + Thread.CurrentThread.ManagedThreadId; });
// Action that prints out ThreadName for the current thread Action action = () => { // If ThreadName.IsValueCreated is true, it means that we are not the // first action to run on this thread. bool repeat = ThreadName.IsValueCreated;
// Launch eight of them. On 4 cores or less, you should see some repeat ThreadNames Parallel.Invoke(action, action, action, action, action, action, action, action);
// Dispose when you are done ThreadName.Dispose(); } } // This multithreading example can produce different outputs for each 'action' invocation and will vary with each run. // Therefore, the example output will resemble but may not exactly match the following output (from a 4 core processor): // ThreadName = Thread5 // ThreadName = Thread6 // ThreadName = Thread4 // ThreadName = Thread6 (repeat) // ThreadName = Thread1 // ThreadName = Thread4 (repeat) // ThreadName = Thread7 // ThreadName = Thread5 (repeat)