Async等待Task.FromResult(0)

问题描述 投票:2回答:3

不知道我是否对我对async await如何工作的理解感到困惑,但这是我坚持的问题。考虑一个人为的例子

  1. 此代码阻止UI public async void LoginButtonClicked() { //create a continuation point so every following statement will get executed as ContinueWith await Task.FromResult(0); //this call takes time to execute Remote.Login("user","password"); }
  2. 但这不(显然) public void LoginButtonClicked() { Task.Run(()=>{ Remote.Login("user","password");}); }

我喜欢使用方法1,因为我不想使用Task.Run来旋转长时间的工作,而是我更喜欢框架处理这个形式我。但问题是对方法1的调用似乎是阻塞的。

c# async-await
3个回答
4
投票

如果您调用的所有长时间运行的操作都是异步的,则使用await / async仅阻止您阻止UI。在您的示例中,您的Remote.Login是同步调用,因此无论先前的await行如何操作,都将阻止您的UI。

您需要获得实际长时间运行操作的异步版本(例如返回Task的东西)或者如果不可能,那么您可以使用Task.Run将此工作移至ThreadPool

如果可能,你想要什么:

public async void LoginButtonClicked()
{
    await Remote.LoginAsync("user","password");
    // do anything else required
}

1
投票

每个异步方法都有其上下文。

当任务开始时,它可能会在新的SynchronizationContext中运行。 “可能”,因为如果任务已经完成,如Task.FromResult(0),则不会创建其他SynchronizationContext并使用原始的Task.ConfigureAwait(continueOnCapturedContext: false)

等待任务意味着当任务完成时,下一个语句将在原始SynchronizationContext中运行。

可以使用Task.FromResult(0).ConfigureAwait(false)更改此行为。这意味着下一个语句将在相同的上下文中继续。但是,这将通过执行Remote.Login("user","password");来改变,因为任务已经完成并且将使用原始上下文。

因此,您的public async void LoginButtonClicked() { await Task.Delay(5000).ConfigureAwait(false); Remote.Login("user","password"); } 将在原始上下文中运行,从而阻止在相同上下文中运行的UI线程。

如果你有类似的东西:

Remote.Login("user","password");

然后Remote.LoginAsync()将在线程池上下文中执行,因此处于与原始UI上下文不同的上下文中。

因此,修复代码的最佳方法是创建一个Task.ConfigureAwait(false),如@Nicholas W回答中所述。

关于性能的说明:如果你有一个带有多个await语句的异步方法,并且你不需要其中一些等待在UI或web应用程序线程上工作,那么你可以使用 async Task LoginAsync(string user, string password) { Remote.Login(user, password); await Task.FromResult(0); } 来防止多个切换到UI /切片执行时间的web-app上下文。


-2
投票
  1. 你并行运行Task.FromResult(0);并仍在等待Remote.Login(“用户”,“密码”);完成
  2. 你运行Remote.Login(“user”,“password”);异步。

您必须创建Remote.Login的异步版本

    public async void LoginButtonClicked()
    {
        await LoginAsync("user", "password");
    }

并称之为

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.