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

Jac*_*val 4 c# xaml multithreading asynchronous async-await

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

在我的代码隐藏文件中,我使用Dispatcher在UI线程上运行任何UI更新.我发现的每个例子都表明在使用'回调'类型场景时这是一个很好的做法但我在使用异步时没有看到它.根据我对async的理解,似乎每当我想在任何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
    });
}
Run Code Online (Sandbox Code Playgroud)

我只需要访问UIContext并且线程无关紧要吗?如果有人能为我澄清这一点会很棒.

Tho*_*que 8

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

不完全......如果启动异步操作的线程具有同步上下文(对于UI线程为true),则执行将始终在同一线程上继续执行,除非您明确指定不捕获同步上下文.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
    });
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然在UI情况下确实如此,但在一般情况下`SynchronizationContext`!= thread.一个值得注意的例子是ASP.NET,其中`AspNetSynchronizationContext`指的是"请求上下文".此外,如果没有`SynchronizationContext`,`await`将回退到当前的`TaskScheduler`(虽然这在实践中并不常见). (7认同)