0
async void Main()
{
    T0.TT();
}

private class T0
{
    [ThreadStatic] private static int test;

    public static async void TT()
    {
        test = 4;
        var continuation = new System.Threading.Tasks.TaskCompletionSource<int>(System.Threading.Tasks.TaskContinuationOptions.RunContinuationsAsynchronously);
        var th = new Thread(() => { Thread.Sleep(500); Console.WriteLine(test); test = 3; continuation.TrySetResult(5); test = 7; });
        th.Start();
        Console.WriteLine(await continuation.Task);
        Console.WriteLine(test);
    }
}
Output:
0
5
3

So without the System.Threading.Tasks.TaskContinuationOptions.RunContinuationsAsynchronously this was written to demonstrate the rest of the async method runs on the thread created by new Thread(). However with System.Threading.Tasks.TaskContinuationOptions.RunContinuationsAsynchronously it still somehow finds that specific [ThreadStatic] value that is set in the newly created thread (thus can't be a TaskScheduler thread) and cleared as soon as TrySetResult returns.

What the hey? How is this happening?

Joshua
  • 40,822
  • 8
  • 72
  • 132

1 Answers1

3

You should be passing TaskCreationOptions.RunContinuationsAsynchronously, not TaskContinuationOptions.RunContinuationsAsynchronously.

Passing TaskContinuationOptions.RunContinuationsAsynchronously will call the overload that takes an object parameter, treating it as a "state" object and not as a flag controlling the TCS behavior.

Stephen Cleary
  • 437,863
  • 77
  • 675
  • 810