C# 5中的async/await线程机制感觉不对?

11

为什么调用线程要进入异步方法,直到内部的 'await'?

直接在调用异步方法时生成一个线程不是更简洁吗?这样你可以确定异步方法立即返回。你不必担心在异步方法的早期阶段执行任何昂贵的操作。

我倾向于知道一个方法是否会在“我的”线程上执行代码,以及它是否会阻塞。该模型似乎打开了一整个介于两者之间的可能性。

设计者比我聪明得多,所以我相信他们有很好的理由,我只是想弄清楚。


你不需要为异步方法添加async关键字,而是为调用异步代码的方法添加。 - Tim Mahy
只是想澄清一下:我喜欢那种语法糖,它意味着你不需要回调来执行异步操作。但线程流动的方式让我感到有些不安。 - Jamona Mican
3个回答

38
在调用异步方法时,只需立即生成一个线程不是更好吗?"异步"方法的整个意义在于避免生成新线程。您正在将异步性与并发混淆。异步方法不需要在另一个线程上运行才能是异步的。异步方法的重点在于它们允许您将工作分解成需要按特定顺序运行但不一定要在同一线程中运行其他工作的小块。 请将线程视为可以雇用的工人。将异步方法视为具有项目之间暂停的待办事项列表。如果您的待办事项列表说“去商店,买牛奶和鸡蛋,回家,做一个煎蛋卷”,则异步方法的好处在于,当有人在“买鸡蛋”步骤和“回家”步骤之间打电话给您,并说“你能在回家的路上顺便在药房取我的处方吗?”您可以在制作煎蛋卷之前接听电话并安排工作。对于非异步方法,您的手机会一直响,直到煎蛋卷做好,然后您才接听电话。UI将阻止直到您完成正在进行的工作。 您的概念是为了保持UI线程响应,一旦得到待办事项列表,就去雇用一些人替您跑到商店买东西,以便您可以自由接听有关药房的电话。那是昂贵而不必要的。使用异步,因为长时间运行的任务内置了UI可以中断和安排更多工作的点,所以一切都可以保持在同一个线程上。

很棒的比喻!只要我不会长时间暂停,无法接听电话,这个方法就可以很好地运作。有了一个雇佣工人,我肯定永远不会错过任何一个电话。当我有便宜的人可以雇用(生成线程)时,担心错过电话是我感到不安的根源,所以这个比喻甚至可以解释我的感受。接受答案! - Jamona Mican
2
如果你认为生成线程是“廉价”的话,那么异步可能一开始对你来说就不是必需的。我认为生成线程是极其昂贵的,因此应该尽量避免。 - Eric Lippert
好的。我不做太多UI编程,所以也许这就是为什么我从未意识到它们有多昂贵...无论如何,线程生成的开销很大确实回答了我的问题。 - Jamona Mican
3
对我来说,避免使用额外线程带来的性能消耗甚至不是最具有说服力的论点。它可以避免我的核心代码在多个线程上运行时所涉及的复杂性。 - CodesInChaos
Async/Await并不排除工作会在另一个线程上执行。这取决于Awaiter的实现,对吧? - LBushkin
1
@LBushkin:没错;工作或其中的一部分可以在另一个线程上执行。但异步方法本质上会启动另一个线程的想法是错误的。 - Eric Lippert

3

我认为async..await续传式编程的语法糖。

因此,它与线程无关。


2

我倾向于知道一个方法是否会在“我的”线程上执行代码。

我认为这是一种特殊的愿望,不是针对任何特性的好或坏的论据。

异步/等待的主要优点是可以将启动异步操作和处理结果的代码放在一个方法中。

如果没有它,您就必须将逻辑上属于同一部分的代码分成两部分。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接