あらゆる場所でモーダルダイアログボックスを使用するレガシーコードを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;
}
これは、2つのボタンを使用してポップアップを開いたり閉じたりする最初の1〜2回の試行でうまく機能するようです。ただし、数回試行した後、Windows.UI.Xaml.dll
nullポインターを逆参照しようとすると、アプリケーションはすぐに深くクラッシュします。これをC#で再現することもできます(実質的に同じコードで)。
誰かがアイデアを持っていますか、ここで何が起こっているのですか?または、代替アプローチの提案ですか?