I've been having issues passing around a Culture between threads. I've managed to get it somewhat working using a Synchronization context, but in one part of my code I use a Task.Yield(). After this piece of code, my context is lost meaning all subsequent awaits/yields after this point do not use my custom SynchronizationContext.
I've boiled it down to a very simple test and I can see that after our Task.Yield, Our SynchronizationContext is lost.
Synchronization Context Class :
public class TestSynchronizationContext : SynchronizationContext
{
}
Unit Test :
[Test]
public async Task TestHere()
{
TestSynchronizationContext context = new TestSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(context);
var something1 = SynchronizationContext.Current;
await Task.Yield();
var something = SynchronizationContext.Current;
}
EDIT : If I use a new Task, the context is preserved if I can pass in the correct TaskScheduler (Although... It's the scheduler, not the Synchronization context). Such as the following :
[Test]
public async Task TestHere()
{
TestSynchronizationContext context = new TestSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(context);
CultureInfo taskCulture = null;
Task.Factory.StartNew(
() => { taskContext = SynchronizationContext.Current; },
CancellationToken.None,
TaskCreationOptions.None,
TaskScheduler.FromCurrentSynchronizationContext()
).Wait();
Assert.AreEqual(context.GetType(), taskContext.GetType());
}
Your SychronizationContext
must set itself as Current
. If your SynchronizationContext
is for a dedicated thread, you can just set current once in your main loop; if it uses thread pool threads to execute (as in your example code), you should set it whenever you borrow one of the threads (and clear it before returning the thread to the thread pool, of course).