title: C# multithreading combined with async/await
body: <p>This is yet another question related to multi-threading in C#.</p>
  
  <p>However, when multi-threading combined with async/await seems to be interesting.</p>
  
  <p>I have a method generating threads which invoke methods of objects asynchronously. </p>
  
  <p>However, the context is not shared by objects of different classes.</p>
  
  <p>For example, consider the code</p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Text;
  using System.Threading;
  using System.Threading.Tasks;
  
  namespace ThreadDataSharing
  {
      class Data
      {
          public static ThreadLocal&lt;string&gt; Name = new ThreadLocal&lt;string&gt;();
      }
  
      class Locker { public static object lobj = new object { };}
      class Program2
      {
          static void Main(string[] args)
          {
              for (int i = 0; i &lt; 3; i++)
              {
                  var pObj = new Program();
                  new Thread(new ThreadStart(pObj.MyThreadMethod)).Start();
              }
          }
      }
      class Program
      {
  
          ///my async method
          ///
          public async Task MyAsyncMethod()
          {
              lock (Locker.lobj)
              {
                  Console.WriteLine("From async method");
                  Console.WriteLine("thread: " + Thread.CurrentThread.ManagedThreadId);
                  Console.WriteLine("id: " + Data.Name.Value);
              }
  
              await MyAsyncMethod2();
  
              await new AsyncClass().AsyncMethod();
          }
  
          public async Task MyAsyncMethod2()
          {
              lock (Locker.lobj)
              {
                  Console.WriteLine("From async 2 method");
                  Console.WriteLine("thread: " + Thread.CurrentThread.ManagedThreadId);
                  Console.WriteLine("id: " + Data.Name.Value);
              }
  
              await Task.Run(() =&gt;
              {
                  lock (Locker.lobj)
                  {
                      Console.WriteLine("From task run method");
                      Console.WriteLine("thread: " + Thread.CurrentThread.ManagedThreadId);
                      Console.WriteLine("id: " + Data.Name.Value);
                  }
              });
          }
  
          public void MyThreadMethod()
          {
              lock (Locker.lobj)
              {
                  Console.WriteLine("From thread method");
                  Console.WriteLine("thread: " + Thread.CurrentThread.ManagedThreadId);
  
                  var id = Guid.NewGuid();
                  Data.Name.Value = id.ToString();
                  Console.WriteLine("id: " + Data.Name.Value);
              }
  
              MyAsyncMethod().Wait();
          }
      }
  
  
      public class AsyncClass
      {
          public async Task AsyncMethod()
          {
              lock (Locker.lobj)
              {
                  Console.WriteLine("From class async method");
                  Console.WriteLine("thread: " + Thread.CurrentThread.ManagedThreadId);
                  Console.WriteLine("id: " + Data.Name.Value);
              }
  
              var newId = Guid.NewGuid();
              Data.Name.Value = newId.ToString();
  
              await AsyncMethod2();
          }
  
          public async Task AsyncMethod2()
          {
              lock (Locker.lobj)
              {
                  Console.WriteLine("From class async 2 method");
                  Console.WriteLine("thread: " + Thread.CurrentThread.ManagedThreadId);
                  Console.WriteLine("id: " + Data.Name.Value);
              }
  
              await Task.Run(() =&gt; { });
          }
      }
  
  }
  </code></pre>
  
  <p>Running this code produces the following output on my machine</p>
  
  <pre><code>From thread method
  thread: 3
  id: 3a7ef8e3-ebe1-49e1-94bb-798358ac1567
  From thread method
  thread: 4
  id: 341d3371-f905-4e1c-aac3-47bda16c8d88
  From thread method
  thread: 5
  id: b7e79901-81b7-430f-b158-59f091e43a0c
  From async method
  thread: 3
  id: 3a7ef8e3-ebe1-49e1-94bb-798358ac1567
  From async method
  thread: 5
  id: b7e79901-81b7-430f-b158-59f091e43a0c
  From async method
  thread: 4
  id: 341d3371-f905-4e1c-aac3-47bda16c8d88
  From async 2 method
  thread: 3
  id: 3a7ef8e3-ebe1-49e1-94bb-798358ac1567
  From async 2 method
  thread: 4
  id: 341d3371-f905-4e1c-aac3-47bda16c8d88
  From async 2 method
  thread: 5
  id: b7e79901-81b7-430f-b158-59f091e43a0c
  From task run method
  thread: 6
  id:
  From task run method
  thread: 8
  id:
  From task run method
  thread: 7
  id:
  From class async method
  thread: 7
  id:
  From class async method
  thread: 6
  id:
  From class async method
  thread: 8
  id:
  From class async 2 method
  thread: 8
  id: f52ed654-0e55-4906-bfc1-65c6b25a7785
  From class async 2 method
  thread: 7
  id: 1e53e03b-a3a0-4296-8622-7716b45d1462
  From class async 2 method
  thread: 6
  id: 1adca81d-b11a-4860-b37d-a017afe877b8
  </code></pre>
  
  <p>Question is, why is it not sharing the <code>ThreadLocal&lt;T&gt;</code> object with the instance of the second Class (<code>AsyncClass</code>)?</p>