【问题标题】:Two level async-await call两级异步等待调用
【发布时间】:2013-09-22 13:08:28
【问题描述】:

最近我遇到了一些使用 async-await 的异步代码。我的问题是下面两个代码块有什么区别 -

代码块 - 1

public async Task Method1(string fileName)
{
    await Method2(fileName);
}

public async Task Method2(string filePath)
{
    await Task.Run(() =>{
         //do some task
    });
}

代码块 - 2

public async Task Method1(string fileName)
{
    await Method2(fileName);
}

public async Task Method2(string filePath)
{
    Task.Run(() =>{
         //do some task
    });
}

这两个代码的区别在于Method2上的await。当第三种方法(比如 Method3)调用 Method1 时会发生什么?从 Method3 观察到的执行有什么不同?

【问题讨论】:

  • 代码 #2 应该给你一个警告,解释到底有什么区别。不要忽略来自编译器的警告。
  • @svick 谢谢。编译器说该方法缺少 await 运算符,将同步运行。现在,想想我提到的方法3。当method3调用method1时,在两种情况下都到达await调用后控制权返回给method3。那么,有什么区别呢?
  • 不同之处在于从Method1 返回的Task 何时完成。使用#2,它将立即完成(不等待在Task.Run() 开始的Task 完成)。

标签: c# async-await


【解决方案1】:

Method2 存在严重问题:

public async Task Method2(string filePath)
{
    Task.Run(() =>{
         //do some task
    });
}

它同步运行并返回一个完整的Task 对象(Task.IsComplete == true)。但是,在它返回之前,它会启动另一个任务(使用Task.Run),该任务异步运行并且完成状态结果会丢失(“一劳永逸”)。这样说会更有意义:

public Task Method2(string filePath)
{
    return Task.Run(() =>{
         //do some task
    });
}

【讨论】:

    【解决方案2】:

    在第二个代码块中,Method2 将完成,无需等待 Method2 中的 Task.Run 完成。

    这取决于您在实施方面的需要。例如,如果你想在 Method2 中初始化一个变量,而被调用方希望这个变量被初始化,那么第二个代码块将导致意外错误。

    【讨论】:

    • 对不起,我没看清楚。能详细解释一下吗?
    • 在代码块 2 中,Method2 运行一个任务。假设这个任务需要 10 秒才能完成。 Method2 实际上会在任务完成之前完成。这意味着您可以运行 Method2 而无需等待 10 秒完成并在此期间做其他事情......喝咖啡或不喝咖啡
    • no 在代码块一中,Task 前面的 await 语句是指令等待任务完成,然后才能执行方法 2 的其余代码。跨度>
    • 想想方法1。在这两种情况下,控件都会立即返回给方法 1,因为在 Task.Run() 之后没有任何操作。
    • 你的例子是伪代码,想象一下这两个任务都在实现一些非常复杂的东西,需要 10 秒。在您的第一个示例中,Method2 需要 10 秒才能完成,因为任务需要很长时间...在第二个示例中,Method2 将立即返回,因为它不等待任务完成...
    猜你喜欢
    • 2021-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    • 1970-01-01
    相关资源
    最近更新 更多