通用应用程序中未处理异常处理程序中的异步方法

3

我正在编写未处理异常事件的处理程序,我们将把异常转储到文件中,然后发送到服务器进行进一步分析。现在它只会显示崩溃已发生。我订阅了该事件。在该方法中,我调用了一个处理错误的函数。但是,当我在该方法中编写以下代码时:

public async Task HandleException(Exception exception)
{
    var dialog = new MessageDialog(exception.Message, "Exception occurred");
    await dialog.ShowAsync();
}

当以调试模式运行它时,Visual Studio将显示Visual Studio Just-In-Time调试器。起初我认为问题出在我试图在GUI线程关闭时显示消息框上。我将函数更改为:
public async Task HandleManagedException(Exception 
{ 
    await FileStorage.WriteToFileAsync("someFile.txt", exception.ToString());
}

FileStorage.WriteToFileAsync 函数的样子如下:

public async Task WriteToFileAsync(string filename, string data)
{
    var file = await this.storageFolder.CreateFileAsync(filename, CreationCollisionOption.ReplaceExisting);
    await FileIO.WriteTextAsync(file, data);
}

在调试模式下,当我在await FileIO.WriteTextAsync(file,data)上设置断点时,它会停在那里。按下继续按钮后,与先前代码相同的窗口显示。当从XAML事件调用它时,它可以正常运行。我已经在Google和StackOverflow中搜索了未处理异常处理程序中的异步方法,但没有任何与我的问题相关的内容。
我的问题是:这个错误的原因是什么?在未处理异常处理程序中使用异步方法是否可能?
更新: 非常感谢迄今为止提供的答案。第二个问题我自己回答了,在关闭代码调试后,结果证明是可能的,并且该函数按预期工作。

你确定你的代码读取的是 WriteToFileAsync("someFile., exception.ToString()); 吗? - BugFinder
是的,我很确定,因为我在“await FileIO.WriteTextAsync(file, data);”上设置了断点,运行调试器后它停在那里。 - Maxi King
由于缺少引号,看起来你有一个问题。 - BugFinder
你在JIT对话框中看到了什么错误信息?不要在异常对话框中取消选中“用户未处理”复选框,否则它将被隐藏。 - fahadash
我收到警告:“调试器已连接到'some file',但未配置为调试此未处理的异常。要调试此异常,请分离当前调试器。在我提到的对话框中,有一条消息:“.exe中发生了一个未处理的win32异常,错误码为[6972]”。 - Maxi King
啊,是的,我最喜欢的最糟糕的异常消息…… - DotNetRussell
1个回答

5
为了避免出现Visual Studio Just-In-Time Debugger对话框,我们可以按照以下方式将UnhandledExceptionEventArgs.Handled属性设置为true:
```UnhandledExceptionEventArgs.Handled```
public App()
{
    this.InitializeComponent();
    this.Suspending += OnSuspending;
    this.UnhandledException += App_UnhandledException;
}

private async void App_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
    e.Handled = true;
    await HandleException(e.Exception);
}

public async Task HandleException(Exception exception)
{
    var dialog = new MessageDialog(exception.Message, "Exception occurred");
    await dialog.ShowAsync();
}

在调试模式下,由于App.g.i.cs中存在以下代码,您会收到警告和即时调试器对话框:
#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
UnhandledException += (sender, e) =>
{
    if (global::System.Diagnostics.Debugger.IsAttached) 
        global::System.Diagnostics.Debugger.Break();
};
#endif

这些代码是在构建项目时自动生成的。从这些代码中,我们可以发现在调试模式下是否有未处理的异常,它将调用 Debugger.Break 方法,从而导致警告和即时调试器对话框。
在处理程序中设置e.Handled = true; 可以避免这种情况。更多信息,请参考此类似问题:如何尝试捕获所有异常。但是,如您所见,这只会在调试模式下发生,在发布模式下,您的代码应该可以正常工作。

我认为问题在于为什么我们需要这样做... 为什么这个调试不像 WPF 一样好笑。 - DotNetRussell
我检查了那个属性,它是有效的。然而,我更喜欢在未处理的异常后退出应用程序,而不是显示对话框。有其他方法可以不显示弹出窗口吗? - Maxi King
@MaxiKing,恐怕没有其他办法了。这些代码是自动生成的,用于帮助我们调试未处理的异常。通常情况下,当我们遇到未处理的异常时,Visual Studio会在这个方法中断,并且我们可以从e参数中获取异常信息。在这种情况下,我们应该停止调试并处理这个异常。正如我所说的,这只会在调试模式下发生,在发布模式下,Windows Runtime会在未处理的异常后终止您的应用程序,并且不会出现对话框。 - Jay Zuo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接