Why does ConfigureAwait (false) not work when Task.Run () works?

I call the asynchronous library method with ConfigureAwait (false). But I'm still at a standstill. (I use it in the ASP.NET API) But, if I use the same method enclosed in Task.Run (), it works fine.

My understanding: if the library method does not use ConfigureAwait inside, then adding ConfigureAwait will not solve the problem, since in the library call this will lead to a deadlock (we block it with .Result). But, if so, why does it work in Task.Run (), since it will not be able to continue in the same context / thread.

This is stated in the article . By the way, I have many articles by Stephen Cleary. But why Task.Run () works in secret.

Code snippet:

// This Create Method results in Deadlock public async Task<string> Create(MyConfig config) { Document doc = await Client.CreateDocumentAsync(CollectionUri, config).ConfigureAwait(false); return doc.Id; } // Uses Task.Run() which works properly, why?? public string Create(MyConfig config) { Document doc = Task.Run(() => Client.CreateDocumentAsync(CollectionUri, config)).Result; return doc.Id; } [HttpPost] public ActionResult CreateConfig(MyConfig config) { string id = Create(config).Result; return Json(id); } 
+7
c # async-await
source share
2 answers

In the first example, the implementation of Client.CreateDocumentAsync is deadlocked because it is trying to continue using the current SynchronizationContext .

When using Task.Run delegate will be called in the ThreadPool thread, which means that there will be no current SynchronizationContext , so all continuations will be resumed using the ThreadPool thread. This means that it will not be inhibited.

Of interest, why is your CreateConfig method not asynchronous? The latest versions of MVC and WebAPI support asynchronous methods, getting rid of .Result would be a better solution.

+5
source share

I believe Lucasoid is true. In other words...

 // This Create Method results in Deadlock public async Task<string> Create(MyConfig config) { Document doc = await Client.CreateDocumentAsync(CollectionUri, config).ConfigureAwait(false); return doc.Id; } 

You can't just stick to ConfigureAwait(false) at the same level, and this will magically prevent deadlocks. ConfigureAwait(false) can only prevent deadlocks if it is used by each await to transitively close this method and all methods that it calls.

In other words, ConfigureAwait(false) needs to be used for every await in Create (which it is), and it also needs to be used for every await in CreateDocumentAsync (which we put on t), and it also needs to be used for each await in each method, which calls CreateDocumentAsync etc.

This is one of the reasons why it is such a fragile "solution" to the deadlock problem.

+4
source share

All Articles