我目前正在编写大量 async
库代码,并且我知道在每次异步调用之后添加 ConfigureAwait(false)
的做法,以便避免将延续代码编码回原始(通常是 UI)线程上下文。由于我不喜欢未标记的 bool 参数,因此我倾向于将其写为 ConfigureAwait(continueOnCapturedContext: false)
。
我添加了一个扩展方法以使其更具可读性(并减少了输入):
public static class TaskExtensions
{
public static ConfiguredTaskAwaitable<TResult> WithoutCapturingContext<TResult>(this Task<TResult> task)
{
return task.ConfigureAwait(continueOnCapturedContext: false);
}
public static ConfiguredTaskAwaitable WithoutCapturingContext(this Task task)
{
return task.ConfigureAwait(continueOnCapturedContext: false);
}
}
所以现在我可以用 await SomethingAsync().WithoutCapturingContext()
代替 await SomethingAsync().ConfigureAwait(continueOnCapturedContext: false)
。我认为这是一个改进,但是当我不得不在同一个代码块中调用多个 async
方法时,即使这样也开始感到厌烦,因为我最终得到的结果与此类似:
await FooAsync().WithoutCapturingContext();
var bar = await BarAsync().WithoutCapturingContext();
await MoreFooAsync().WithoutCapturingContext();
var moreBar = await MoreBarAsync().WithoutCapturingContext();
// etc, etc
在我看来,它开始降低代码的可读性。
我的问题基本上是这样的:有没有办法进一步减少它(除了缩短扩展方法的名称)?
最佳答案
没有全局设置来阻止方法中的任务捕获同步上下文,但是您可以做的是仅更改该方法范围内的同步上下文。在您的特定情况下,您可以仅针对该方法的范围将上下文更改为默认同步上下文。
编写一个简单的一次性类来更改同步上下文然后在处理时将其更改回来是很容易的:
public class SyncrhonizationContextChange : IDisposable
{
private SynchronizationContext previous;
public SyncrhonizationContextChange(SynchronizationContext newContext = null)
{
previous = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(newContext);
}
public void Dispose()
{
SynchronizationContext.SetSynchronizationContext(previous);
}
}
允许你写:
using(var change = new SyncrhonizationContextChange())
{
await FooAsync();
var bar = await BarAsync();
await MoreFooAsync();
var moreBar = await MoreBarAsync();
}
(注意将上下文设置为 null
意味着它将使用默认上下文。)
关于c# - 是否有比在异步方法中调用 ConfigureAwait(false) 更具可读性的替代方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27109285/