C# 多消息对话框应用程序崩溃

C# 多消息对话框应用程序崩溃,c#,windows-runtime,C#,Windows Runtime,我在我的应用程序的多个地方使用messagedialogs。问题是,只要任何消息对话框(或系统警报,如功能警告)处于活动状态,并且调用另一个my消息对话框,应用程序就会毫无例外地崩溃,或者出现取消筛选访问异常 这是我如何称呼MessageDialog的: CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { MessageDialog msg2 =

我在我的应用程序的多个地方使用
messagedialogs
。问题是,只要任何
消息对话框
(或系统警报,如功能警告)处于活动状态,并且调用另一个my
消息对话框
,应用程序就会毫无例外地崩溃,或者出现
取消筛选访问异常

这是我如何称呼MessageDialog的:

CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
    MessageDialog msg2 = new MessageDialog(_resourceLoader.GetString("MsgGPSUnavailable"));
    msg2.ShowAsync();
});
我认为应该等待对话框关闭,但通过使用
Dispatcher
我将此对话框排队到主UI线程,主UI线程是否自行处理?谢谢你对这个问题的解释

编辑-我一步一步地进行,得到了下面的代码,它包含在同一个类中。当我运行应用程序时,会调用LoadDataToModel。这是确定的,对话框由msgGPSDisabled显示。在此之后,将引发事件并调用locator_StatusChanged。这也可以,并显示对话框。 现在是奇怪的部分。当我在LoadDataToModel中未调用msgGPSDisabled,并且仅在locator_StatusChanged中调用msgGPSDisabled时,应用程序在显示对话框后立即崩溃。没有异常,在第47行打开App.g.i.cs(调试和禁用\u XAML\u生成的\u中断\u未处理的\u异常)。即使我用try-catch,它也可以用在任何地方。当我在locator_StatusChanged中使用msgGPSDisabled而不使用Dispatcher时,会引发异常。不可捕获,“未找到项目”


您的lambda仍应等待异步调用,这样当调度器运行它时,它将不会继续,直到消息框关闭

我还没有尝试过,但这应该会有所帮助(注意
async
await
关键字的用法):

编辑:

正如Filip已经解释过的,您不能同时显示多个消息框。他还提出了一些避免问题的方法


在您的场景(报告GPS状态更改)中,最好将状态显示为UI中的标签,因为您实际上不需要用户以任何方式响应。您甚至可以在值在列表中更改时收集它们,并使用
ItemsControl
显示它们,以便用户可以观察更改的历史记录(可能带有时间戳)。这完全取决于您想要实现的目标。

两个
消息对话框不能同时显示。如果您想继续使用
MessageDialogs
,您有几个选项,并且最好使用某种
MessageDialogService
来管理调用以打开对话框:

  • 需要打开新对话框时,请关闭现有对话框。这是最简单的选择,也可能是最好的选择,尽管您可能会取消一个对话框,而这个对话框可能在某种程度上很重要,这取决于您的对话框是关于什么的
  • 对对话框进行排队,以便旧对话框不会被取消,但新对话框会在旧对话框取消后显示。这将确保用户关闭所有对话框,但如果你的应用程序能够以某种方式开始显示数百个对话框,那么这可能是一个问题
  • 只有在没有显示的情况下才打开一个新的。现在,这样做的风险是没有显示新的消息,这听起来比第一个选项更有问题
如果您想使用队列选项-您可以使用以下代码:

using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Popups;
using Windows.UI.Xaml;

namespace WinRTXamlToolkit.Controls.Extensions
{
    /// <summary>
    /// MessageDialog extension methods
    /// </summary>
    public static class MessageDialogExtensions
    {
        private static TaskCompletionSource<MessageDialog> _currentDialogShowRequest;

        /// <summary>
        /// Begins an asynchronous operation showing a dialog.
        /// If another dialog is already shown using
        /// ShowAsyncQueue or ShowAsyncIfPossible method - it will wait
        /// for that previous dialog to be dismissed before showing the new one.
        /// </summary>
        /// <param name="dialog">The dialog.</param>
        /// <returns></returns>
        /// <exception cref="System.InvalidOperationException">This method can only be invoked from UI thread.</exception>
        public static async Task<IUICommand> ShowAsyncQueue(this MessageDialog dialog)
        {
            if (!Window.Current.Dispatcher.HasThreadAccess)
            {
                throw new InvalidOperationException("This method can only be invoked from UI thread.");
            }

            while (_currentDialogShowRequest != null)
            {
                await _currentDialogShowRequest.Task;
            }

            var request = _currentDialogShowRequest = new TaskCompletionSource<MessageDialog>();
            var result = await dialog.ShowAsync();
            _currentDialogShowRequest = null;
            request.SetResult(dialog);

            return result;
        }
    }
}
使用制度;
使用System.Threading.Tasks;
使用Windows基金会;
使用Windows.UI.Popups;
使用Windows.UI.Xaml;
命名空间WinRTXamlToolkit.Controls.Extensions
{
/// 
///MessageDialog扩展方法
/// 
公共静态类MessageDialogExtensions
{
私有静态任务完成源\u currentDialogShowRequest;
/// 
///开始显示对话框的异步操作。
///如果已使用显示另一个对话框
///ShowAsyncQueue或ShowAsyncIffable方法-它将等待
///用于在显示新对话框之前取消上一个对话框。
/// 
///对话。
/// 
///此方法只能从UI线程调用。
公共静态异步任务ShowAsyncQueue(此消息对话框)
{
如果(!Window.Current.Dispatcher.HasThreadAccess)
{
抛出新的InvalidOperationException(“此方法只能从UI线程调用”);
}
while(_currentDialogShowRequest!=null)
{
等待_currentDialogShowRequest.Task;
}
var request=_currentDialogShowRequest=new TaskCompletionSource();
var result=wait dialog.ShowAsync();
_currentDialogShowRequest=null;
request.SetResult(对话框);
返回结果;
}
}
}

谢谢,但它的行为仍然很奇怪,当我在主页构造函数中使用它时,它工作正常。当我在其他地方使用它时,它就不会了。@Qerts你可以发布一些复制你的问题的示例代码吗。它是否仍然以同样的错误使应用程序崩溃?非常感谢。这解决了我的问题,挽救了我的理智!
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
{
    MessageDialog msg2 = new MessageDialog(_resourceLoader.GetString("MsgGPSUnavailable"));
    await msg2.ShowAsync();
});
using System;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.UI.Popups;
using Windows.UI.Xaml;

namespace WinRTXamlToolkit.Controls.Extensions
{
    /// <summary>
    /// MessageDialog extension methods
    /// </summary>
    public static class MessageDialogExtensions
    {
        private static TaskCompletionSource<MessageDialog> _currentDialogShowRequest;

        /// <summary>
        /// Begins an asynchronous operation showing a dialog.
        /// If another dialog is already shown using
        /// ShowAsyncQueue or ShowAsyncIfPossible method - it will wait
        /// for that previous dialog to be dismissed before showing the new one.
        /// </summary>
        /// <param name="dialog">The dialog.</param>
        /// <returns></returns>
        /// <exception cref="System.InvalidOperationException">This method can only be invoked from UI thread.</exception>
        public static async Task<IUICommand> ShowAsyncQueue(this MessageDialog dialog)
        {
            if (!Window.Current.Dispatcher.HasThreadAccess)
            {
                throw new InvalidOperationException("This method can only be invoked from UI thread.");
            }

            while (_currentDialogShowRequest != null)
            {
                await _currentDialogShowRequest.Task;
            }

            var request = _currentDialogShowRequest = new TaskCompletionSource<MessageDialog>();
            var result = await dialog.ShowAsync();
            _currentDialogShowRequest = null;
            request.SetResult(dialog);

            return result;
        }
    }
}