由于捕获到异常,显示WinRT MessageDialog的正确方式是什么

本文关键字:方式 是什么 MessageDialog WinRT 于捕获 异常 显示 | 更新日期: 2023-09-27 18:24:38

由于捕获到异常,显示消息对话框的正确方式是什么?

我最初尝试

try
{
    await DoSomething();
}
catch(InvalidOperation ex)
{
    await MessageDialog(ex.Message).ShowAsync();
}
catch(CommunicationException)
{
    await MessageDialog(StringResourceLoader.LoginError).ShowAsync();
}

这不起作用,因为您不能在try块内await。去掉等待命令会使编译器显示以下警告:

因为不等待此调用,所以在调用完成之前继续执行当前方法。考虑将"等待"运算符应用于呼叫的结果

我不喜欢在代码中保留这些警告,因为在某些地方,人们忘记了使用await,因此很难找到错误。

将消息对话框语句更改为var task = new MessageDialog(ex.Message).ShowAsync().AsTask();可以消除所有警告和错误,但我不确定这是一个好的方法(从技术上讲,这是不好的,因为它希望我await调用)

最后,我尝试存储异常,并在catch之外执行向用户显示什么的逻辑(包括确定抛出了什么类型的异常的所有逻辑),通过:

Exception thrownException = null;
try
{
    await DoSomething();
}
catch(Exception ex)
{
    thrownException = ex;
}
if (thrownException is InvalidOperationException)
    await MessageDialog(ex.Message).ShowAsync();
else if (thrownException is CommunicationException)
    await MessageDialog(StringResourceLoader.LoginError).ShowAsync();

我也不确定我是否觉得这是最好的方法。有什么想法吗?

由于捕获到异常,显示WinRT MessageDialog的正确方式是什么

编辑:在Hans对其他问题发表评论后,我最终通过创建以下类来解决它:

public static class MessageDialogDisplayer
{
    private static readonly ConcurrentQueue<MessageDialog> _dialogQueue;
    private static readonly CancellationTokenSource _cancellationTokenSource;
    static MessageDialogDisplayer()
    {
        _dialogQueue = new ConcurrentQueue<MessageDialog>();
        _cancellationTokenSource = new CancellationTokenSource();
        new Task(DisplayQueuedDialogs, _cancellationTokenSource.Token).Start();
    }
    public static void DisplayDialog(MessageDialog dialog)
    {
        _dialogQueue.Enqueue(dialog);
    }
    private static async void DisplayQueuedDialogs()
    {
        const int millisecondsBetweenDialogChecks = 500;
        while (!_cancellationTokenSource.Token.IsCancellationRequested)
        {
            MessageDialog dialogToDisplay;
            if (_dialogQueue.TryDequeue(out dialogToDisplay))
            {
                await dialogToDisplay.ShowAsync();
            }
            else
            {
                await Task.Delay(millisecondsBetweenDialogChecks);
            }
        }
    }
}

这已将我的try/catch语句更改为

MessageDialog errorDialog = null;
try
{
    await DoSomething();
}
catch(InvalidOperation ex)
{
    MessageDialogDisplayer.DisplayDialog(new MessageDialog(ex.Message));
}
catch(CommunicationException)
{
    MessageDialogDisplayer.DisplayDialog(new MessageDialog(StringResourceLoader.LoginError));
}

从长远来看,这会使事情更加稳定(一旦我将所有消息对话框调用程序转换为使用它而不是showAsyncing本身),并使try/catch块不那么混乱(imo)。