我正在编写大量的异步库代码,我知道在每次异步调用之后添加ConfigureAwait(false)的做法,以避免将继续代码编组回原来的(通常是UI)线程上下文.因为我不喜欢未标记的布尔参数,所以我倾向于将其写为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); } }
所以现在我可以有一些东西像等待SomethingAsync().WithoutCapturingContext()而不是等待SomethingAsync().ConfigureAwait(continueOnCapturedContext:false).我认为这是一个改进,但是即使这样,当我必须在同一个代码块中调用一些异步方法时,我开始琢磨,因为我最终得到了类似的东西:
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表示将使用默认上下文.)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。