Best practice to call ConfigureAwait for all server-side code

前端 未结 4 823
既然无缘
既然无缘 2020-11-22 04:06

When you have server-side code (i.e. some ApiController) and your functions are asynchronous - so they return Task - is it consid

4条回答
  •  闹比i
    闹比i (楼主)
    2020-11-22 04:22

    Brief answer to your question: No. You shouldn't call ConfigureAwait(false) at the application level like that.

    TL;DR version of the long answer: If you are writing a library where you don't know your consumer and don't need a synchronization context (which you shouldn't in a library I believe), you should always use ConfigureAwait(false). Otherwise, the consumers of your library may face deadlocks by consuming your asynchronous methods in a blocking fashion. This depends on the situation.

    Here is a bit more detailed explanation on the importance of ConfigureAwait method (a quote from my blog post):

    When you are awaiting on a method with await keyword, compiler generates bunch of code in behalf of you. One of the purposes of this action is to handle synchronization with the UI (or main) thread. The key component of this feature is the SynchronizationContext.Current which gets the synchronization context for the current thread. SynchronizationContext.Current is populated depending on the environment you are in. The GetAwaiter method of Task looks up for SynchronizationContext.Current. If current synchronization context is not null, the continuation that gets passed to that awaiter will get posted back to that synchronization context.

    When consuming a method, which uses the new asynchronous language features, in a blocking fashion, you will end up with a deadlock if you have an available SynchronizationContext. When you are consuming such methods in a blocking fashion (waiting on the Task with Wait method or taking the result directly from the Result property of the Task), you will block the main thread at the same time. When eventually the Task completes inside that method in the threadpool, it is going to invoke the continuation to post back to the main thread because SynchronizationContext.Current is available and captured. But there is a problem here: the UI thread is blocked and you have a deadlock!

    Also, here are two great articles for you which are exactly for your question:

    • The Perfect Recipe to Shoot Yourself in The Foot - Ending up with a Deadlock Using the C# 5.0 Asynchronous Language Features
    • Asynchronous .NET Client Libraries for Your HTTP API and Awareness of async/await's Bad Effects

    Finally, there is a great short video from Lucian Wischik exactly on this topic: Async library methods should consider using Task.ConfigureAwait(false).

    Hope this helps.

提交回复
热议问题