问题
It's well-known that in a general-purpose library, ConfigureAwait(false)
should be used on every await call to avoid continuing on the current SynchronizationContext.
As an alternative to peppering the entire codebase with ConfigureAwait(false)
, one could simply set the SynchronizationContext to null once, at the public surface method, and restore it before returning to the user. In other words:
public async Task SomeSurfaceMethod()
{
var callerSyncCtx = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
try
{
// Do work
}
finally
{
SynchronizationContext.SetSynchronizationContext(callerSyncCtx);
}
}
This could also be wrapped in a using
for better readability.
Is there a disadvantage to this approach, does it not end up producing the same effect?
The major advantage is obviously readability - the removal of all ConfigureAwait(false)
calls. It may also reduce the likelihood of forgetting a ConfigureAwait(false)
somewhere (although analyzers mitigate this, and it could be argued that developers could just as well forget changing the SynchronizationContext).
A somewhat exotic advantage is not embedding the choice of capturing the SynchronizationContext or not in all methods. In other words, in one case I may want to run method X with a SynchronizationContext, while in another I may want to run the same method without one. When ConfigureAwait(false)
is embedded everywhere that isn't possible. Granted, this is quite a rare requirement, but I bumped into it while working on Npgsql (triggering this question).
回答1:
As @MrinalKamboj wrote in the comments, the approach of temporarily setting the SynchronizationContext to null at the public surface method and setting back has already been proposed here. There doesn't seem to be any specific problem associated with this (see Stephen Cleary's answer here).
来源:https://stackoverflow.com/questions/39447571/async-library-best-practice-configureawaitfalse-vs-setting-the-synchronizati