Pregunta

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?

¿Fue útil?

Solución

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.

There is no easy way to create a synchronous wrapper for an asynchronous method. It's best to let asynchronous methods be asynchronous.

You can use ConfigureAwait(continueOnCapturedContext: false) to discard the context, but it won't be any better than Task.Run in your case since you can't change the methods that M calls.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top