Consider the following code:
public Task SomeAsyncMethod()
{
var tcs = new TaskCompletionSource();
... do something, NOT setting the TaskCompletionSource...
return tcs.Task
}
public void Callsite1()
{
await SomeAsyncMethod();
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
}
public void Callsite2()
{
SomeAsyncMethod().ContinueWith((task) =>
{
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
});
}
At some point in time, the TaskCompletionSource created in SomeAsyncMethod is set on a ThreadPool Thread:
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId);
tcs.SetResult();
When the Task from the TaskCompletionSource is awaited (as in Callsite1), the continuation executes synchronously on the Thread that called SetResult. When ContinueWith is called (as in Callsite2), the continuation executes asynchronously on a different thread.
It does not help to call configure the await, as in
public void Callsite1()
{
await SomeAsyncMethod().ConfigureAwait(true or false);
}
and this is not even the point of this question. As the implementor of SomeAsyncMethod, I do not want to call some potentially unknown code by calling SetResult. I want to have the continuation always scheduled asynchronously. And I cannot rely on the caller to configure the await properly (if that would even work).
How can a TaskCompletionSource be configured such that its Task doesn't execute its continuation synchronously when it's awaited?