异步操作立即等待

3

我正在查看另一位开发者的这些代码:

  bool isValid = await engine.GetTaskByIdAsync(taskId);
  if(isValid )
  ....

当我使用async操作时,它是为了在异步操作完成时进行独立的工作:

  Task<bool> task = engine.GetTaskByIdAsync(taskId);

  //Do work that doesn't need the "task" variable

  bool completed = await task;
  if(bool)
  ....

看起来第一个示例启动了异步操作,然后立即开始等待。我是否有所不理解?

注:此代码位于应用程序的数据访问层中,因此它不与用户界面交互。


当然可以启动一个进程并立即返回,如果您之前有逻辑,那又有什么关系呢? - Kevin DiTraglia
似乎第一个示例启动了异步操作,然后立即开始等待 - await 强制我们在继续之前等待调用完成。 - Dan
你该如何在不等待任务的情况下完成那位程序员所做的事情? - Servy
5
不,它并不会。这是一个常见的误解。实际上,它会将整个方法剩余部分作为等待任务完成后要执行的续体进行连接。与等待该任务完成非常不同。 - Servy
立即等待的使用旨在方便不锁定用户界面。 - Travis J
@Servy 我现在感觉好蠢啊。;-;。 - Dan
2个回答

6

这里有一个我不理解的价值吗?

当然有-它意味着虽然在做更多工作之前需要该操作返回的值,但等待期间没有占用线程。如果您编写GUI,则这尤其重要,因为占用GUI线程基本上意味着冻结UI。

听起来您正在关注异步性的“并行执行多个任务”方面,这很重要,但远非它唯一的好处。


好的,我专门从事网络工作,所以这不是我通常处理的事情。我在数据访问层中找到了这段代码,所以很好奇是否有什么可以从中获得的东西。 - Mister Epic
1
@ChrisHardie 网络应用程序仍然可以从异步操作中受益。它可以使网络请求在不执行 CPU 绑定工作时不消耗线程池线程的时间,从而使这些线程池线程为其他请求提供服务,允许服务器扩展它可以处理的可能并发请求的数量。 - Servy
@AVee 线程无法无限扩展。它们有成本。当您没有实际任务需要执行时,不消耗线程的时间意味着您不需要使用太多线程来完成相同数量的工作。如果您已经运行了硬件支持的最大线程数,则意味着可以完成更多的工作。这里的整个想法并不是让您从CPU中获得更高的吞吐量;而是在没有CPU绑定工作需要执行时不会占用线程的时间。这一切都是关于有效地完成非CPU绑定的工作。 - Servy
2
@AVee 不,await不需要实际的线程来做任何工作。异步的整个重点是,除非你在CPU绑定的工作中使用它们,否则你实际上不会使用线程。在正确编写的异步程序中,进行非CPU绑定工作时真的没有线程。 - Servy
1
假设您有1000个同时执行的请求,所有这些请求都需要执行需要一秒钟的基于IO的操作(例如Web服务调用)。使用async/await,您可以摆脱单个线程(或者说,只有实际上能够同时执行工作的线程数量)。如果同步地进行调用,则需要1000个线程,所有这些线程都被阻塞,并且除了吸收1GB堆栈空间之外什么也不做。基本上,您认为阻塞的线程是免费的- Servy和我正在说它们不是。 - Jon Skeet
显示剩余5条评论

0
常见的错误是认为await会阻塞,但实际上并不会。
当前线程会立即返回,剩余的函数部分会在异步任务完成时被执行。

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