Let's say I want to write an async method M. I don't know what kind of synchronization context will be used (UI, ASP.NET, Console app, etc.) to call it. I'd like to make the method as easy to use as possible. That means that anyone should be able to call it synchronously by accessing the Result member of the returned Task.
public async Task<int> M()
{
// lot's of calling of helper methods including awaits, etc.
// helper methods not owned by me
// ...
return 42;
}
// this should be safe to do from any synchronization context
int result = M().Result; // Synchronously wait
The problem is that the synchronization context of the caller of method M is leaked to the callees of M. If any one of them wants to continue on the passed in synchronization context, then it can deadlock (e.g. when using the UI synchronization context).
One solution to forget the synchronization context when M is called is to wrap the content of M in Task.Run. However, that will force a thread jump, including in cases when all tasks inside M are complete and everything could synchronously run on the same thread without context switches. Is there a better solution to forget the synchronization context of a thread? Or am I missing something, which would make this question irrelevant?