【问题标题】:Confused about dispatcher and async对调度程序和异步感到困惑
【发布时间】:2014-05-21 06:54:38
【问题描述】:

我正在制作一个 Windows 8.1 平板电脑应用程序,并且大量使用 async 关键字。 我对 async 关键字的理解是,虽然它对程序员来说似乎是同步的,但不能保证当你的 await 完成时你会在同一个线程上运行。

在我的代码隐藏文件中,我使用 Dispatcher 在 UI 线程上运行任何 UI 更新。我发现的每个示例都表明,在使用“回调”类型场景时这是一个很好的做法,但在使用异步时我没有看到任何提及。根据我对异步的理解,每当我想在任何 await 调用之后更新 UI 时,我似乎都需要使用调度程序。

我试图通过将我的理解写在下面的代码中来更清楚。

private void SomeEventHandler(object sender, RoutedEventArgs e)
{
    UpdateUI(); //This should run in my UI thread
    await Foo(); //When Foo returns I have no guarantee that I am in the same thread
    UpdateUI(); //This could potentially give me an error
    await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
    {
        UpdateUI(); //This will run in the UI thread
    });
}

我是否只需要访问 UIContext 而线程无关紧要?如果有人能为我澄清这一点,那就太好了。

【问题讨论】:

    标签: c# multithreading xaml asynchronous async-await


    【解决方案1】:

    我对 async 关键字的理解是,虽然它对程序员来说似乎是同步的,但不能保证当你的 await 完成时你会在同一个线程上运行。

    不完全... .ConfigureAwait(false).

    如果没有同步上下文,或者如果它没有被捕获,那么将在ThreadPool 线程上继续执行(除非等待的任务实际上是同步完成的,在这种情况下你会留在同一个线程上)。

    所以,这是您的代码 sn-p 与更新的 cmets:

    private void SomeEventHandler(object sender, RoutedEventArgs e)
    {
        UpdateUI(); //This should run in my UI thread
        await Foo(); //When Foo returns I am still in the UI thread
        UpdateUI(); //This will work fine, as I'm still in the UI thread
    
        // This is useless, since I'm already in the UI thread ;-)
        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            UpdateUI(); //This will run in the UI thread
        });
    }
    

    【讨论】:

    • 虽然在 UI 情况下是这样,但在一般情况下 SynchronizationContext != 线程。一个值得注意的例子是 ASP.NET,其中AspNetSynchronizationContext 指的是“请求上下文”。此外,如果没有 SynchronizationContextawait 将回退到当前的 TaskScheduler(尽管这在实践中并不常见)。
    猜你喜欢
    • 1970-01-01
    • 2016-12-08
    • 2020-10-23
    • 2021-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多