没有线程或异步设备,async / await模式是否无关紧要?

时间:2015-10-19 19:23:52

标签: .net multithreading async-await

编辑 - 阅读下面的三个答案后,我意识到我在胡说八道!抱歉浪费你宝贵的一些时间,并感谢你澄清了很多误解,真的! :)

我假设apples and pipe wrenches与async / await的方式相同,而线程也是类似问题的解决方案。 Async/awaitThreads都解决了UI响应问题,但不是以相同的方式。前者是一种模式,可以在异步收集多个所需结果时使用(例如为了改善用户体验),因此它被称为“异步”。繁重的工作,需要几秒钟到几小时的工作必须在另一个线程上卸载以保持UI响应。这两者完全不同。

无论我如何编辑这个问题,都无法在有或没有线程问题的情况下询问async / await,因为它们是完全不同的东西,可以一起使用(在很多方面)或单独使用。下面的声明.2说明了一切(除了“调用”误解),但我从一开始就没有真正理解它的真正含义。

我想我应该从怀疑的那一刻起删除这个问题,但在实际阅读一些答案之前,我无法理解它是多么愚蠢。但是,这也可能有助于其他人更好地了解async / await是什么。

顺便说一句,我不知道答案是什么答案,因为他们都有有价值的信息。

原帖

值得注意的是,我“又是另一个异步/等待初学者”。但是,到目前为止我所理解的是:

  1. async / await不会创建threads!从不!它们与调用者在同一个线程上运行。
  2. async / await不是并行任务。他们只是定义了一种模式,在调用者级别调用await时,会执行异步代码块(或者说 - 我知道我的理解有点错误,但这就是我能清楚地想到它的想法)。
  3. 如果该块不包含await关键字,则不会异步执行代码块。
  4. async / await似乎可以很好地处理一些I / O任务,但在大多数高CPU计算中似乎都不太好。
  5. async / await似乎失败了Thread.Sleep(应改为使用Task.Delay)或Exception Finally阻止。{/ li>

    基于以上所述,为了简化操作,我认为async / await只是 goto 的一种改进形式,能够从方法步骤跳转到另一个方法步骤,因为goto呼叫可以“飞行”(被延迟),直到遇到等待! (对不起,简化目前的事情)

    我已经测试了I / O和CPU代码而没有额外的线程,两者都很重,并且两者都产生了无响应 UI,直到所有内容都完成。

    我的观察

    没有异步功能之类的东西:

    • 使用框架中众多.net对象之一或其自己创建线程的成员明确定义的线程
    • 设计为从硬件级别(CPU)开始异步工作的
    • IO devices

    async/await只是简单的同步模式;意思是,只有async/await个关键字在任何地方都没有类似异步的东西。

      

    问题是:上述观察结果是真的,还是我遗漏了async/await的一些重要内容?

    附注:

    我读过这个blog post没有线程,Stephen Cleary的博客)。他声明没有线程(完全同意),但它与我的观察结果并不矛盾,在没有涉及异步设备的纯程序员代码级别,除非您在另一个线程中委派繁重的任务,否则不能拥有响应式UI。我关心的不是模式的 awaitable 方面,正如我所说,它就像一个飞行的goto;我想确保我不是为了使用新的东西而盲目地使用async/await

    .ConfigureAwait(false):似乎涉及一个ThreadPool,这就是为什么UI线程仍然响应......

3 个答案:

答案 0 :(得分:3)

Async-await是一种模式,允许您编写与同步代码非常相似但实际上可以异步执行的代码。这依赖于编译器完成的大量工作。就是这样。

Async-await不会创建异步操作,它只允许您以简单的方式使用它们,并且仍然是异步的,与使用BeginXXX / EndXXX之前不同。

确实,异步对I / O非常有用,因为大多数异步操作都是I / O操作,但有不同的操作,如Task.Delay,异步同步机制或异步等待事件。

关于您的具体要点:

  1. Async-await不会创建线程。异步方法开始在调用程序线程上运行,不要使用任何线程进行实际异步操作,并在ThreadPool线程或SynchronizationContext或{{ 1}}。
  2. 未调用Await。当异步方法在未完成的任务上达到等待时,该方法的其余部分将被安排为在该任务完成时运行的延续。
  3. 差不多。您需要等待异步操作异步操作才能异步。
  4. Async-await适用于两者。如果您的操作不是异步的,那么使用async-await是没有意义的。
  5. Async-await不会因TaskScheduler而失败。使用Thread.Sleep来阻止线程是浪费的。这就是你使用Thread.Sleep的原因。您现在可以使用C#6等待Task.Delay
  6. 最后:

      

    意思是,只有async / await关键字在任何地方都没有类似异步的东西。

    是的,使用finally关键字标记方法不会使任何异步运行。它只允许您使用async并将结果包装在await

答案 1 :(得分:3)

您可能会发现我的async intro有帮助。

我会说asyncawait使用异步操作的最佳方式。作为副产品,async还会创建更高级别的异步操作(如果方法返回Task / Task<T>)。但是,它们不是从无到有创建异步操作的好方法。

所以我不同意这句话:

  

async / await只是简单的同步模式

但是,我同意await只是async方法分解为多个同步部分的声明。

如果你有CPU绑定代码并且你不想阻止UI线程,那么你可以使用类似Task.Run的东西将该代码推送到线程池线程。然后,UI代码可以awaitTask.Run返回任务。

答案 2 :(得分:2)

这里有两个截然不同的概念。 异步并行并不是一回事。虽然异步操作可以隐藏多线程,但他们不一定会这样做。

C#中的async / await关键字只是表达诸如“当操作A完成时,执行操作B”之类的想法的语法糖。操作A是否在另一个线程上运行是一个您不关心的实现细节。

基本上,您让编译器和框架为您解决问题。

如果你想到它,async / await在概念上可能与事件和事件循环的工作方式有些相似。也许event语法不够灵活,这也是他们引入这些新关键字的原因。就我个人而言,我认为它与JavaScript中的promises相同,或者Node.js中的事件循环是如何工作的。我并不是说它的工作方式类似,但确实解决了类似的问题。