Reputation: 2843
This is yet another question related to multi-threading in C#.
However, when multi-threading combined with async/await seems to be interesting.
I have a method generating threads which invoke methods of objects asynchronously.
However, the context is not shared by objects of different classes.
For example, consider the 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<string> Name = new ThreadLocal<string>();
}
class Locker { public static object lobj = new object { };}
class Program2
{
static void Main(string[] args)
{
for (int i = 0; i < 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(() =>
{
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(() => { });
}
}
}
Running this code produces the following output on my machine
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
Question is, why is it not sharing the ThreadLocal<T>
object with the instance of the second Class (AsyncClass
)?
Upvotes: 2
Views: 1680
Reputation: 457187
the context is not shared by objects of different classes.
Actually, the behavior you're seeing is that the (thread-local) context is not shared between threads.
I have an async intro blog post that may clear up this behavior. The essential concept is that async
methods do not resume on the same thread; rather, they resume on a captured context (by default). In this case, the thread pool context is used to resume your async
methods, which means that those continuations are just scheduled to the thread pool, and may be run by any thread pool thread.
Upvotes: 2
Reputation: 2989
In a Console app with await/async there isn't shared synchronization context, may be this is the reason why it's not shared.
Upvotes: 3