Joshua
Joshua

Reputation: 43327

Strange case involving TaskContinuationOptions.RunContinuationsAsynchronously

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?

Upvotes: 0

Views: 187

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 457197

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.

Upvotes: 3

Related Questions