c#异步任务:是否所有参与的方法都必须是异步的?

本文关键字:异步 方法 任务 是否 | 更新日期: 2023-09-27 18:06:05

当我们处理异步任务时,任务由多个方法调用(可能是其他类的)组成,这些方法调用又由进一步的方法调用组成。我们可以称它为树。是否所有的方法都必须是类型异步任务的原始任务真正异步行为?对于其他类似语言(主要是Java)的任何类型的后台任务,答案是正确的吗?(在c#中,一旦我在这个树中的某个地方有一个方法进入无限循环(谈论一个长时间运行的任务!),然而遗憾的是,原始异步任务的isRunning属性返回false。)

c#异步任务:是否所有参与的方法都必须是异步的?

是否所有的方法都必须是async task类型的原始任务真正异步行为?

为了异步操作,async方法必须有一个await语句用于一个尚未完成的操作。

我想我的async介绍博客会对你有帮助。

这个答案是否适用于其他类似语言的任何类型的后台任务,主要是Java ?

是的。

遗憾的是,原始异步任务的isRunning属性返回false

我认为你的意思是TaskStatus不是TaskStatus.Running。这是正常和预期的,因为异步任务是承诺任务,而不是委托任务(查看我的博客了解更多信息)。

简短的回答是否定的。异步意味着由另一个进程完成的工作可以被传递给该进程,因此不会阻塞调用线程。如果这些进程不在同一台机器上,那就更好了,因为这些工作在调用者处占用的计算或IO很少。这是通过使用async/await机制挂起方法执行来实现的,该机制承诺一旦完成就在某些同步上下文上恢复。那么,为什么要进行概述呢?

因为这意味着我们可以而且应该明智地选择那些应该是异步的操作,因此在异步方法中应用await关键字。有些不需要它,因为它们是轻量级的,并且由于异步状态机的创建,向它们添加异步甚至可能会增加计算时间。因此,方法中的操作通常可以是异步和同步代码的混合。

这反过来意味着一些方法将使用async/await的Task返回类型,而一些方法将是常规的同步方法。

不,他们不需要。简单的例子,在一个表单应用程序中

button.Click += async (_, __) =>
                {
                    await Task.Run(() => MyClass.SomeTimeconsumingMethod());
                };

仍然允许您在执行SomeTimeconsumingMethod期间移动窗口,而这个

button.Click += (_, __) =>
                {
                    MyClass.SomeTimeconsumingMethod();
                };

不允许你这么做

使用await关键字的唯一要求是您正在等待的方法返回TaskTask<T>

这个方法的确切实现(asyncreturn someTask)对代码的正确性没有影响,尽管它可能会影响函数。

任何正常的代码都可以在async方法中与await调用一起运行。唯一重要的限制是不允许使用outref

是否所有的方法都必须是async task类型才能使原始任务真正异步?

这取决于你所说的"all"这个词是什么意思。

一些api不能是异步的。以List<T>.Add为例。你真的希望它是异步的吗?
有些api应该是异步的,但是没有相应的异步api(例如SMO或File静态类)。

理想情况下你应该做"异步所有的方式",当谈论io绑定操作。但是,当async方法链的某些部分将同步执行io绑定操作时,IRL可能会面临违反此规则的情况。