当我不能使用 ConfigureAwait(false) 时?
When I cannot use ConfigureAwait(false)?
根据最佳实践,如果可以,建议将 .ConfigureAwait(false)
与 async/await
关键字结合使用:
await Task.Run(RunSomethingAsync).ConfigureAwait(false);
能否请您举例说明我无法使用.ConfigureAwait(false)
的情况?
你 "cannot" 使用 ConfigureAwait(false)
当你真正关心你所在的同步上下文时。例如,假设 GUI申请:
public async void SomeButtonClick(object sender, EventArgs e)
{
var result = await SomeAsyncOperation().ConfigureAwait(false);
textBox.Text = result;
}
当您从 ConfigureAwait
return 时,您将不会回到 UI 线程。这将导致 InvalidOperationException
.
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!
根据最佳实践,如果可以,建议将 .ConfigureAwait(false)
与 async/await
关键字结合使用:
await Task.Run(RunSomethingAsync).ConfigureAwait(false);
能否请您举例说明我无法使用.ConfigureAwait(false)
的情况?
你 "cannot" 使用 ConfigureAwait(false)
当你真正关心你所在的同步上下文时。例如,假设 GUI申请:
public async void SomeButtonClick(object sender, EventArgs e)
{
var result = await SomeAsyncOperation().ConfigureAwait(false);
textBox.Text = result;
}
当您从 ConfigureAwait
return 时,您将不会回到 UI 线程。这将导致 InvalidOperationException
.
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. TheGetAwaiter
method of Task looks up forSynchronizationContext.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!