2012-08-30 59 views
1

我必須將一些遺留代碼移植到Metro/WinRT(使用C++/CX),並使用模式對話框。由於這些對話框提供了自己的消息循環(使用DialogBoxParam()),調用代碼將一直等待,直到用戶單擊消息框上的一個按鈕。CoreDispatcher.ProcessEvents()會導致間接崩潰?

我正在嘗試爲舊的消息框類,它使用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#中重現這一點(使用幾乎相同的代碼)。

有沒有人有一個想法,這裏發生了什麼?或者有其他方法的建議?

回答

0

如果有人有興趣:我問同樣的問題,幾天後在MSDN論壇上,並從微軟員工得到了迴應有:

http://social.msdn.microsoft.com/Forums/en-US/winappswithnativecode/thread/11fa65e7-90b7-41f5-9884-80064ec6e2d8/

顯然,這裏的問題是嵌套的消息循環這是由事件處理程序內調用ProcessEvents引起的。看起來WinRT並不支持這個功能,但它沒有以明確的方式失敗,這可能會導致崩潰。

唉,這是我能找到的最好也是唯一的答案,所以我最終通過將事件處理程序(和許多其他代碼)分派到另一個線程來解決問題。然後,我可以通過等待用戶點擊/點擊我的XAML「對話框」彈出框上的按鈕時發出的事件來模擬DialogBox()/DialogBoxParam()(主線程外部)的等待行爲。

0

工作正常,我一個解決辦法是更換線路:

Window::Current->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); 

有:

auto myDispatchedHandler = ref new DispatchedHandler([&](){ 
    Window::Current->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); 
}); 
dispatcher->RunAsync(CoreDispatcherPriority::Normal,myDispatchedHandler); 

欲瞭解更多信息請參閱this post在MSDN。