确保UI更新位于UI线程上

时间:2014-01-14 02:05:26

标签: c# async-await

考虑:

async Task FooAsync()
{
    await BarAsync().ConfigureAwait(false);

    UpdateUI(); // Bug
}

我正在寻找一种系统地确保不会发生这种情况的方法。

也许是一种命名约定,其中必须在UI线程上运行的方法获得特殊后缀。或静态检查,其中方法上的[UIThreadOnlyAttribute]意味着任何调用者必须具有相同的属性,并且可能不会调用ConfigureAwait(false)

有什么建议吗?

3 个答案:

答案 0 :(得分:7)

只要您的应用程序合理分层,就不应该成为问题。

UI层(例如,事件处理程序)和逻辑UI层(例如,ViewModel)需要UI上下文,不应使用ConfigureAwait。其他图层应使用ConfigureAwait。这是一个很适合我的简单指南。

答案 1 :(得分:2)

作为完整性检查,在UpdateUI方法的开头,您可以手动验证当前线程是否具有正确的同步上下文。对于WinForms应用程序,它可能如下所示:

void UpdateUI()
{
    Debug.Assert(SynchronizationContext.Current is WindowsFormsSynchronizationContext);
    // ... 
    // Do the actual UI update
}

对于WPF应用,第一行是:

Debug.Assert(SynchronizationContext.Current is DispatcherSynchronizationContext);

这适合我。

答案 2 :(得分:0)

可以使用编译时代码注入(例如PostSharp)来执行此操作。我从来没有做过这样的事情,但文档似乎表明你可以提出一个创造性的解决方案。使用PostSharp链接到Custom Architecture Constraints