我必须将一些遗留代码移植到 Metro/WinRT(使用 C++/CX)。因为这些对话框提供了它们自己的消息循环(使用DialogBoxParam()
),所以调用代码将一直等到用户单击了消息框上的按钮。
我目前正在尝试为使用 XAML 和弹出控件的旧消息框类编写替代品。要重现相同的行为,我必须在调用线程中等待,但还必须保持 UI 响应。我发现,它CoreDispatcher::ProcessEvents()
可以在循环中使用,以继续处理事件(是的,我意识到这不是很漂亮,但我不想将我们所有的遗留代码更改为新的线程模型)。但是,我遇到了一个让我的应用程序不断崩溃的问题。
这是一个重现该问题的最小示例(只需创建一个 XAML 应用程序并将其连接到一个按钮):
void CPPXamlTest::MainPage::Button_Click_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
bool cancel = false;
auto popup = ref new Popup();
auto button = ref new Button();
button->Content = "Boom";
auto token = (button->Click += ref new RoutedEventHandler([&cancel] (Object ^, RoutedEventArgs ^) { cancel = true; }));
popup->Child = button;
popup->IsOpen = true;
while (!cancel)
{
Window::Current->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending);
}
popup->IsOpen = false;
button->Click -= token;
}
这似乎适用于使用两个按钮打开和关闭弹出窗口的前一两次尝试。然而,经过几次尝试,应用程序将立即崩溃Windows.UI.Xaml.dll
,同时尝试取消引用空指针。我也可以在 C# 中重现它(使用几乎相同的代码)。
有谁知道,这里发生了什么?或者对替代方法的建议?