【问题标题】:Async method await keyword doesn't suspend to calling method异步方法 await 关键字不会暂停到调用方法
【发布时间】:2017-11-06 16:36:04
【问题描述】:

我有以下代码行,以了解 async-await 并暂停直到等待的任务完成。

public async Task<string> WaitAsynchronouslyAsync()
    {
        var results = await WaitAsync();
        Console.WriteLine($@"I am not waiting");
        return results;
    }

    public async Task<string> WaitAsync()
    {
        await Task.Delay(10000).ConfigureAwait(false);
        return "Async programming suspension point demo.";
    }

await 运算符暂停执行,直到 WaitAsync()(延迟 10 秒)方法的工作完成。

与此同时,我期待Console.WriteLine($@"I am not waiting"); 应该将文本写入输出窗口,直到等待的任务完成,因为控制权返回给WaitAsync() 的调用者。当任务完成执行时,await 表达式计算字符串 ("Async programming suspension point demo.")。

我在这里混淆了暂停指针和调试指针吗?

【问题讨论】:

  • 你需要把它转换成正确的英语,这样人们才能真正理解首先发生的事情。完美的语法并不重要(我也不完美),但一个人无法理解你试图谈论的重要事物。
  • await WaitAsync();中删除await,向下移动到return (await results);

标签: c# .net async-await task-parallel-library c#-5.0


【解决方案1】:

await 运算符暂停执行,直到 WaitAsync() 方法的工作完成。

正确。

我期待 Console.WriteLine($@"I am not waiting");应该将文本写入输出窗口,直到等待的任务完成,因为控制权返回给 WaitAsync() 的调用者。

为什么?您刚才说await 运算符会暂停执行,直到工作完成。再过十秒钟,工作就不会完成;工作是等待十秒钟WaitAsync工作直到它执行 return 才完成,那是将来的事情。

正确的做法是让WaitAsynchronouslyAsync 允许调用者有机会在这种情况下运行。

您已经正确地陈述了await 的含义,但您似乎没有完全内化后果。 await 检查其操作数以查看任务是否完成。如果是,则获取任务的结果并继续该方法。如果不是,则将该方法的其余部分注册为该任务的继续,并让出控制权,以便可以在其他地方完成更多工作。将来,当任务完成时,该方法的其余部分将被安排执行。

【讨论】:

  • 是的,我几乎得到了您的澄清,但是,当您说“控制已产生”时,它是否意味着相同,直到等待的任务完成,这里Task.Delay(10000),控制屈服于调用方法和完成其他不等待结果等待方法的任务。所以Console.WriteLine($@"I am not waiting") 应该被打印出来。 简单的await意味着简单地阻止代码的执行,直到任务完成。
  • @AviKenjale 我在回答中介绍了操作顺序。否 await 不会阻塞该方法,它会将控制权返回给调用者,并在 Task 完成后继续执行。
【解决方案2】:

操作顺序如下:

  1. 您拨打WaitAsynchronouslyAsync
  2. WaitAsynchronouslyAsync 致电WaitAsync
  3. WaitAsync 调用Task.Delay(10000).ConfigureAwait(false),产生Task
  4. WaitAsync 返回一个新的Task 给它的调用者WaitAsynchronouslyAsync,稍后会完成
  5. WaitAsynchronouslyAsync 等待来自WaitAsync 的任务,然后返回给它的调用者,提供一个Task 表示它何时完成。
  6. 其他事情发生在调用堆栈的更深处。
  7. Task.Delay 结束,所以WaitAsync 的延续会触发,从中断处继续。
  8. WaitAsync 返回字符串,完成Task
  9. WaitAsynchronouslyAsync 现在可以继续,因为从 WaitAsync 返回的 Task 已经完成。它将继续将文本打印到控制台。
  10. WaitAsynchronouslyAsync 完成这是的任务,让任何有任何设置的人都可以在完成后运行。

【讨论】:

  • 实际上,当光标到达await Task.Delay 时,执行会停在那里并且不会返回到调用方法。我正在阅读这篇文章,并且从那里开始感到困惑。 Microsoft docs link - 带有 await 关键字(前 2 段)
  • @AviKenjale 调试器不会那样做,但那是因为它假定您不想看到调用堆栈进一步发生了什么,而您只是想看看在任务完成并且您的方法准备好继续之后发生。它不能代表幕后实际所做的事情。
【解决方案3】:

await 的意思是“等到异步执行完毕”你的函数在提供的Task 完成执行之前不会继续。

如果您改为说以下内容,它不会等待:

var results = WaitAsync();
Console.WriteLine($@"I am not waiting");
return await results;

或者更简洁,从签名中删除async,然后您就可以使用return results;

【讨论】:

  • 是的,这个我试过了,效果很好。但是,当我阅读 This Microsoft docs link 时,我对 await 关键字(前 2 段)感到困惑
  • @AviKenjale: await 不会阻塞线程,但会阻塞当前方法的执行,因此您的线程可以做其他工作。
猜你喜欢
  • 2017-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 2018-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多