How to tell if the continuation initiated by TaskCompletionSource.TrySetResult
is going to be executed synchronously or asynchronously?
For example:
// class A
void RegisterNotification(TaskCompletionSource<object> tcs)
{
this.source.NotificationEvent += (s, eData) =>
{
Debug.WriteLine("A.before");
tcs.TrySetResult(eData.Result);
Debug.WriteLine("A.after");
DoProcessingA();
};
}
// class B
async Task RequestNotificationAsync()
{
var tcs = new TaskCompletionSource<object>();
this.a.RegisterNotification(tcs);
Debug.WriteLine("B.before");
var data = await tcs.Task;
Debug.WriteLine("B.after");
DoProcessingB();
}
If NotificationEvent
is fired on a thread with the different synchronization context from that of where await tcs.Task
took place, the debug output will be:
B.before
A.before
A.after
B.after
That is, the await tcs.Task
continuation is executed asynchronously. If it is fired on the same synchronization context (or if there is no synchronization context in both places), the output will be:
B.before
A.before
B.after
A.after
That is, the continuation is executed synchronously.
Is there a way to predict this order inside RegisterNotification
?
I could save SynchronizationContext.Current
inside RegisterNotification
and compare it later when I call tcs.TrySetResult
. But that not necessarily mean that await tcs.Task
will take place on the context I saved.
In theory, if I could predict this, I might be able to use it to diagnose and prevent potential deadlocks.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…