一尘不染

异步/等待-什么时候返回Task vs void?

c#

在什么情况下您想使用

public async Task AsyncMethod(int num)

代替

public async void AsyncMethod(int num)

我能想到的唯一情况是您是否需要任务以跟踪其进度。

另外,在以下方法中,async和await关键字是否不必要?

public static async void AsyncMethod2(int num)
{
    await Task.Factory.StartNew(() => Thread.Sleep(num));
}

阅读 323

收藏
2020-05-19

共1个答案

一尘不染

1)通常,您需要返回Task。主要的例外应该是当您 需要
具有void返回类型(用于事件)时。如果没有理由不允许调用者执行await您的任务,为什么要禁止它呢?

2)async返回的方法void在另一方面是特殊的:它们代表 顶级异步操作
,并且在您的任务返回异常时会起作用。最简单的方法是通过一个示例来显示差异:

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();
}

f的例外始终是“遵守”。留下顶级异步方法的异常就像其他未处理的异常一样被对待。g从未观察到例外。当垃圾收集器清理任务时,它会看到任务导致异常,并且没有人处理该异常。发生这种情况时,TaskScheduler.UnobservedTaskException处理程序将运行。您绝对不要让这种情况发生。以您的示例为例,

public static async void AsyncMethod2(int num)
{
    await Task.Factory.StartNew(() => Thread.Sleep(num));
}

是的,请使用asyncawait在这里,它们可以确保如果引发异常,您的方法仍然可以正常工作。

有关更多信息,请参见:http :
//msdn.microsoft.com/zh-
cn/magazine/jj991977.aspx

2020-05-19