C#.NET async等待返回类型

时间:2016-06-14 09:51:54

标签: c# .net asynchronous return async-await

希望有人在C#中使用asyncawait时可以清除返回类型。我们了解到,您有三种返回类型:Task<T>Taskvoid

通过尝试了解这一点,我已经读过你应该只在特殊情况下使用void(事件处理程序),如果要将同步方法更改为async方法,那么你应该更改一个{ {1}}关键字void

我的问题是,我是否需要Task返回类型,即使代码是完全独立的,结果对延续也不重要?比方说,我使用异步方法将一些信息推送到Web服务。

我创建了一个小例子来帮助解释:

Task

我的应用程序有很多这样的方法:

private void CallingMethod()
{
    AsyncMethod();
    AsyncTaskMethod(); // any difference between doing these? (not exc handling)

    var task = AsyncTaskMethod(); // should I do anything with this task
                                  // before I continue? Or is it simply 
                                  // just to show the user that it's async??

    // continue with unrelated code that doesnt require task or any code from above
}

private async void AsyncMethod() // is void okay?
{
    await LongRunningMethod();

    // do other stuff
}

private async Task AsyncTaskMethod() // or should it be Task?
{
    await LongRunningMethod();

    // do other stuff
}

private async Task LongRunningMethod()
{
    // do long running code
}

如果不清楚,请务必说出来,我会尝试整理一下。谢谢你们。

编辑:

private void BigMethod()
{
    DoStuff();

    DoMoreStuff();

    AsyncMethod(); // is this right? Or should I have the task declaration too?

    UnrelatedStuff();
}

private async Task AsyncMethod() // should this return task?
{
    var result = await GetUserId();

    if (result == null)
        return;

    MyUserId = result;
}

private async Task<int> GetUserId()
{
    // do long running code
    return 1;
}

在回复第一条评论时,上面的private void CallingMethod() { AsyncMethod(); } private async void AsyncMethod() { await LongRunningMethod(); } private async Task LongRunningMethod() { await Task.Run(() => { Thread.Sleep(4000); }); MessageBox.Show("Done!"); } 不使用async / await,它会在没有锁定UI线程的情况下快乐地休眠4秒,然后弹出消息框。问题是什么?

2 个答案:

答案 0 :(得分:3)

当方法返回Task时,您不必 使用void,但由于以下几个原因,它确实是首选:

  1. 返回Task(或Task<T>)的异步方法将其异常放在返回的Task上,因此调用方法可以检查(当他们认为合适时)是否Task出现了问题。

  2. Async void方法将它们的异常直接抛出到调用同步上下文中,使它几乎(几乎因为你仍然可以使用全局异常处理程序,但是这样做了对大型应用程序来说无法维护)无法以确定的方式处理它们的异常。

  3. 您基本上无法测试任何可能引发异常的async void方法

  4. async void方法在调用者运行时被认为是完整的。这可能会引入许多问题(实际上,当您尝试将现有库转换为异步时,事件处理程序存在许多问题:继续,获取第三方相对复杂的winforms库并尝试使您的事件处理程序异步,您和# 39;我会看到它造成的破坏!)。

  5. 没有合理的方法可以确定async void方法何时结束(您可以创建自己的SynchronizationContext,但这确实很复杂)

    < / LI>
  6. 您无法配置async void电话(您无法使用ConfigureAwait),因此延续上下文始终是来电者的同步上下文。

  7. 所以......

    TL; DR:除非您无法避免,否则请勿使用async void(即:使用期望void签名的事件处理程序)。这是有原因的。如果您不期望结果,请使用async Task

答案 1 :(得分:1)

您不能等待返回void的方法,并且其中一个主要原因是返回void的异步方法的调用者无法捕获从异步方法抛出的异常。试试这个:

  public void TryToCatchMethod() {
    try {
      MyAsyncMethod();
    } catch (Exception exception) {
      //tha catch is never called
      Debug.WriteLine(exception.ToString());
    }
  }
  public async void MyAsyncMethod() {
    throw new Exception();
  }