c# - 关于线程的混淆以及异步方法在 C# 中是否真正异步

标签 c# .net asynchronous

我正在阅读有关 async/await 的内容以及何时 Task.Yield 可能有用并遇到 this post.我对该帖子的以下内容有疑问:

When you use async/await, there is no guarantee that the method you call when you do await FooAsync() will actually run asynchronously. The internal implementation is free to return using a completely synchronous path.

这对我来说有点不清楚,可能是因为我脑海中的异步定义不一致。

在我看来,由于我主要从事 UI 开发,异步代码是不在 UI 线程上运行,而是在其他线程上运行的代码。我想在我引用的文本中,如果一个方法在任何线程上阻塞(即使它是一个线程池线程),它就不是真正的异步。

问题:

如果我有一个受 CPU 限制的长时间运行的任务(假设它正在做大量的数学运算),那么异步运行该任务一定会阻塞某些线程,对吧?必须做一些实际的计算。如果我等待它,那么某些线程会被阻塞。

真正异步方法的示例是什么?它们实际上是如何工作的?这些是否仅限于利用某些硬件功能的 I/O 操作,因此不会阻塞任何线程?

最佳答案

This is a little unclear to me probably because the definition of asynchronous in my head is not lining up.

很高兴你要求澄清。

In my mind, since I do mainly UI dev, async code is code that does not run on the UI thread, but on some other thread.

这种看法很普遍,但却是错误的。不要求异步代码在任何第二个线程上运行。

假设您正在做早餐。你在 toastr 里放了一些 toast ,在等待 toast 弹出时,你查看了昨天的邮件,支付了一些账单,嘿, toast 弹出了。你付完账单,然后去给你的 toast 涂黄油。

你在哪里雇佣了第二个 worker 来看你的 toastr ?

你没有。线程是 worker 。异步工作流可以全部发生在一个线程上。异步工作流的要点是避免雇佣更多的 worker ,如果你能避免的话。

If I have a long running task that is CPU bound (let's say it is doing a lot of hard math), then running that task asynchronously must be blocking some thread right? Something has to actually do the math.

在这里,我给你一个很难解决的问题。这是一列 100 个数字;请用手把它们加起来。所以你把第一个加到第二个上,做一个总数。然后将运行总计添加到第三个并得到总计。然后,哦,见鬼,第二页的数字不见了。记住你在哪里,然后去 toast 。哦,当干杯时,一封包含剩余数字的信到了。涂完 toast 后,继续将这些数字相加,下次有空时记得吃 toast 。

您雇用另一名 worker 添加数字的部分在哪里? 计算量大的工作不需要同步,也不需要阻塞线程。使计算工作可能异步的是能够停止它,记住你在哪里,去做其他事情,记住在那之后做什么,然后从你离开的地方继续。

现在肯定可能雇用第二个除了加数字什么都不做的 worker ,然后被解雇。你可以问那个 worker “你完成了吗?”如果答案是否定的,你可以去做一个三明治,直到他们完成。这样你和 worker 都很忙。但是没有要求异步涉及多个 worker。

If I await it then some thread is getting blocked.

不不不不。这是你误解的最重要的部分。 await 并不意味着“异步开始这项工作”。 await 的意思是“我这里有一个异步生成的结果可能不可用。如果不可用,在这个线程上找一些其他的工作这样我们就 strong>不阻塞线程。等待是您刚才所说的相反

What is an example of a truly asynchronous method and how would they actually work? Are those limited to I/O operations which take advantage of some hardware capabilities so no thread is ever blocked?

异步工作通常涉及自定义硬件或多线程,但实际上并不需要。

不要考虑 worker 。想想工作流程。异步的本质是将工作流分解成小部分,这样您可以确定这些部分必须发生的顺序,然后依次执行每个部分,但允许相互没有依赖关系的部分交错

在异步工作流中,您可以轻松地检测到工作流中表达各部分之间依赖关系的地方。这些部分用 await 标记。这就是 await 的意思:后面的代码取决于这部分工作流是否完成,所以如果没有完成,就去找其他任务做,等任务完成后再回来完成了。重点是让员工继续工作,即使在未来产生所需结果的世界中也是如此。

关于c# - 关于线程的混淆以及异步方法在 C# 中是否真正异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43989344/

相关文章:

c# - CMake、SWIG 和共享库

.net - 是否可以出于测试目的从 Web 浏览器调用 WCF Web 服务方法?

.net - 为什么 SendMessageTimeout 不更新环境变量?

c# - 为我解释 maxstack 指令

iphone - 我们有什么理由不使用 UIImageView 的子类吗?

javascript - 如何在node.js中的异步方法中处理多个数组

c# - 如何编写一个可以包含其他相关类的类?

C# 关闭时出错

javascript - 如何返回多个异步调用的响应?

c# - 使用接口(interface)的泛型 T 列表