【问题标题】:Am I right to ignore the compiler warning for lacking await for this async call?我是否可以忽略此异步调用缺少等待的编译器警告?
【发布时间】:2012-06-24 05:17:42
【问题描述】:

当我的 Metro 应用程序的一部分发生异常时,我会触发以下方法

void Model_ExceptionOccured(Exception ex)
{
    var dlg = new Windows.UI.Popups.MessageDialog("An exception occured during verification: " + ex.Message, "Exception");
    dlg.ShowAsync();
}

'dlg.ShowAsync()' 调用是异步的,但我不想等待结果。编译器会为它生成一个警告:

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

我应该关心吗?除了摆脱警告之外,还有什么理由我应该添加 await 关键字?

【问题讨论】:

    标签: c# windows-runtime windows-store-apps async-await


    【解决方案1】:

    问题在于,如果dlg.ShowAsync(); 中的代码抛出异常,它将未被处理,并且稍后将由终结器线程重新抛出可能导致您的程序终止。

    实际发生的情况取决于 .NET 异常政策

    MSDN 上的This article 提到了这一点:

    如果您不等待传播异常的任务或访问其 Exception 属性,则在对任务进行垃圾收集时,将根据 .NET 异常策略升级异常。

    当 VS 2012 最终发布时,未处理任务异常的默认策略从终止进程更改为忽略异常。

    【讨论】:

      【解决方案2】:

      根据下面的链接,alexm 给出的答案是不正确的。在未等待的异步调用期间抛出的异常将丢失。要消除此警告,您应该将异步调用的 Task 返回值分配给一个变量。这确保您可以访问任何抛出的异常,这些异常将在返回值中指示。

      http://msdn.microsoft.com/en-us/library/hh965065(v=vs.110).aspx (VB.NET)

      http://msdn.microsoft.com/en-us/library/hh873131.aspx (C#)

      【讨论】:

      • 在 VS2012 中,他们更改了未观察到的任务异常的默认策略。默认行为是终止进程。
      • 您提供的链接显示 VB 特定的错误。你有类似的 C# 参考资料吗?
      • 来自the link: "在大多数情况下,这种行为不是您所期望的。通常调用方法的其他方面取决于调用的结果,或者,至少, 被调用的方法应该在你从包含调用的方法返回之前完成。”这有点道理,尽管如果你将ShowAsync 包装在try 块中并采取链接的建议以完成任务 (Task showAsyncResult = dlg.ShowAsync();),如果不是最佳实践,您仍然可以吗?
      【解决方案3】:

      我遇到了同样的问题,这是我的解决方案:

      我创建了一个 Task 对象,将异步函数的输出分配给 Task 对象,并使用 Timer 定期检查任务的状态。

      下面是一个简短的例子: (在我的 Update_Click 事件处理程序中)

      StatusLabel.Text = "Preparing " + feedArticleList1.Feed.Title;
      UpdateCheck.Enabled = true;
      UpdateTask = feedArticleList1.Feed.UpdateFeedAsync();
      

      稍后,在我的计时器的事件处理程序中,我检查了 UpdateTask.Status:

      switch (UpdateTask.Status)
      {
          case TaskStatus.Canceled:
          case TaskStatus.Created:
          case TaskStatus.Running:
          case TaskStatus.WaitingForActivation:
          case TaskStatus.WaitingForChildrenToComplete:
          case TaskStatus.WaitingToRun:
              StatusLabel.Text = UpdateTask.Status.ToString();
              break;
          case TaskStatus.RanToCompletion:
              StatusLabel.Text = "Update Complete " + DateTime.Now.ToShortTimeString();
              UpdateCheck.Enabled = false;
              break;
          case TaskStatus.Faulted:
              throw (UpdateTask.Exception);
          default:
              break;
      }
      

      【讨论】:

      • 您可以使用任务 Exception 和 ContinueWith 获得相同的效果 - 似乎您正在重新发明轮子,尤其是在异步方法中引入轮询。
      猜你喜欢
      • 2015-08-10
      • 2012-10-25
      • 1970-01-01
      • 2017-05-07
      • 1970-01-01
      • 2016-11-26
      • 1970-01-01
      • 2019-08-27
      • 1970-01-01
      相关资源
      最近更新 更多