对调度程序和异步感到困惑

时间:2014-05-20 22:13:28

标签: c# multithreading xaml asynchronous async-await

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

在我的代码隐藏文件中,我使用Dispatcher在UI线程上运行任何UI更新。我发现的每个例子都表明这在使用“回调”时是一种很好的做法。类型场景,但我在使用异步时没有看到它。根据我对异步的理解,似乎我需要在任何等待调用后更新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,线程并不重要?如果有人能为我澄清这一点会很棒。

1 个答案:

答案 0 :(得分:8)

  

我对async关键字的理解是,虽然它似乎与程序员同步,但无法保证在等待完成时你将在同一个线程上运行。

不完全......如果启动异步操作的线程具有同步上下文(对于UI线程都是如此),则执行将始终在同一线程上继续执行,除非您明确指定不捕获同步上下文.ConfigureAwait(false)

如果没有同步上下文,或者它没有被捕获,那么执行将在ThreadPool线程上恢复(除非等待的任务实际上同步完成,在这种情况下你保持相同线程)。

所以,这是带有更新评论的代码段:

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
    });
}