首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >async/await -何时返回任务vs void?

async/await -何时返回任务vs void?
EN

Stack Overflow用户
提问于 2012-08-27 22:33:40
回答 5查看 408.4K关注 0票数 601

在什么情况下需要使用

代码语言:javascript
复制
public async Task AsyncMethod(int num)

而不是

代码语言:javascript
复制
public async void AsyncMethod(int num)

我能想到的唯一场景是,如果您需要任务能够跟踪其进度。

另外,在下面的方法中,async和await关键字是不必要的吗?

代码语言:javascript
复制
public static async void AsyncMethod2(int num)
{
    await Task.Factory.StartNew(() => Thread.Sleep(num));
}
EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-08-27 22:53:45

通常,您可能希望返回一个

..。主要的例外应该是当您

需求

要有一个

返回类型(用于事件)。如果没有理由不让调用者

你的任务,为什么不允许它?

返回的方法

在另一个方面是特别的:它们代表

顶级异步操作

,并具有在任务返回异常时生效的附加规则。最简单的方法是用一个例子来说明不同之处:

代码语言:javascript
复制
static async void f()
{
    await h();
}

static async Task g()
{
    await h();
}

static async Task h()
{
    throw new NotImplementedException();
}

private void button1_Click(object sender, EventArgs e)
{
    f();
}

private void button2_Click(object sender, EventArgs e)
{
    g();
}

private void button3_Click(object sender, EventArgs e)
{
    GC.Collect();
}

的异常始终是“观察到的”。留下顶级异步方法的异常被简单地视为任何其他未处理的异常。

的异常。当垃圾回收器来清理任务时,它看到该任务导致了异常,并且没有人处理该异常。当这种情况发生时,

处理程序运行。你永远不应该让这种事情发生。为了使用您的示例,

代码语言:javascript
复制
public static async void AsyncMethod2(int num)
{
    await Task.Factory.StartNew(() => Thread.Sleep(num));
}

是,使用

在这里,如果抛出异常,它们会确保你的方法仍然正常工作。

有关详细信息,请参阅:

https://docs.microsoft.com/en-us/archive/msdn-magazine/2013/march/async-await-best-practices-in-asynchronous-programming

票数 492
EN

Stack Overflow用户

发布于 2014-04-11 23:40:56

我偶然读到了这篇非常有用的文章

由杰罗姆·拉班撰写:

https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.html

底线是

可以使系统崩溃,通常应该只在UI端事件处理程序上使用。

这背后的原因是AsyncVoidMethodBuilder使用的同步上下文,在本例中为none。当没有环境同步上下文时,任何未由异步void方法的主体处理的异常都将在ThreadPool上重新引发。虽然似乎没有其他逻辑位置可以抛出这种未处理的异常,但不幸的结果是该进程正在被终止,因为从.NET 2.0开始,ThreadPool上的未处理的异常实际上会终止该进程。您可以使用AppDomain.UnhandledException事件截获所有未处理的异常,但无法从此事件恢复进程。

在编写UI事件处理程序时,异步void方法在某种程度上是无痛的,因为异常的处理方式与非异步方法中的处理方式相同;它们被抛出到调度程序上。有可能从这样的异常中恢复,在大多数情况下都是正确的。然而,在UI事件处理程序之外,异步void方法在某种程度上使用起来很危险,而且可能不容易找到。

票数 52
EN

Stack Overflow用户

发布于 2018-06-19 23:31:20

调用async void的问题是

你甚至连任务都拿不回来。您无法知道函数的任务何时完成。--

异步和等待中的速成课程|旧的新事物

以下是调用异步函数的三种方式:

异步任务SomethingAsync() { ...返回t;}异步任务SomethingAsync() { ... }异步空SomethingAsync() { ... }

在所有情况下,函数都被转换为一系列任务。不同之处在于函数返回的内容。

在第一种情况下,该函数返回一个最终生成t的任务。

在第二种情况下,函数返回一个没有产品的任务,但您仍然可以等待它,以了解它何时运行完成。

第三种情况是令人讨厌的情况。第三种情况类似于第二种情况,只是您甚至没有拿回任务。您无法知道函数的任务何时完成。

async void的情况是“一发即忘”:你启动了任务链,但你并不关心它什么时候结束。当函数返回时,您所知道的就是第一次等待之前的所有操作都已执行。第一次等待之后的所有内容都将在将来您无法访问的某个未指定的点上运行。

票数 40
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12144077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档