Related to a previous question in which a for loop wouldn't work, I 'm trying to replace a MessageBox() call to a WinUI content dialog, which means that the call must block for the caller.
After some hours of trying, I eventually created this one:
ContentDialogResult MainPage::ShowDialogBlocking(winrt::Microsoft::UI::Xaml::Window const& mainWindow)
{
auto top = Content().as<Panel>();
auto dialog = top.FindName(L"ProgressDialog").as<ContentDialog>();
auto dispatcherQueue = mainWindow.DispatcherQueue();
bool completed = false;
ContentDialogResult result = {};
auto as = dialog.ShowAsync();
as.Completed([&](auto const& sender, auto)
{
auto s2 = sender.as< winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult>>();
auto top = Content().as<Panel>();
auto dialog = top.FindName(L"ProgressDialog").as<ContentDialog>();
result = s2.GetResults();
completed = true;
dispatcherQueue.EnqueueEventLoopExit();
});
dispatcherQueue.RunEventLoop();
return result;
}
This works in a way that it actually blocks and when EnqueueEventLoopExit
is called, the RunEventLoop returns.
However at this point the application crashes with an access violation. What could be the problem? It seems that with "EnqueueEventLoopExit" the dispatcher fatally gets released?
Edit: The following seems to work but I'm not sure it is reliable.
void MainPage::ShowDialogBlocking()
{
auto dialog = ... // ContentDialog
ContentDialogResult res;
bool Completed = 0;
auto as = dialog.ShowAsync();
as.Completed([&](auto const& sender, auto)
{
res = sender.as<winrt::Windows::Foundation::IAsyncOperation<ContentDialogResult>>().GetResults();
Completed = 1;
});
while (!Completed)
{
MSG msg;
if (GetMessage(&msg, 0,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}