30

当我的 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 关键字?

4

3 回答 3

28

根据下面的链接,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#)

于 2012-08-27T15:36:16.530 回答
6

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

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

MSDN上的这篇文章提到了这一点:

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

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

于 2012-06-21T21:58:00.550 回答
-1

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

我创建了一个 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;
}
于 2013-07-26T20:29:11.030 回答