I have a MFC application which calls a coroutine named CheckForAppUpdates, from its OnInitDialog function. When the code executes, I get an error message:
this function must be called from a UI thread
Here is the relevant code:
BOOL MainDlg::OnInitDialog() {
CDialogEx::OnInitDialog();
HWND hwnd = GetSafeHwnd();
winrt::init_apartment();
CheckForAppUpdates(hwnd);
// snip
}
winrt::fire_and_forget MainDlg::CheckForAppUpdates(HWND hWnd) {
try {
// Capture the UI thread context
// co_await winrt::resume_foreground(); // needs a Dispatcher.. which needs a..
winrt::apartment_context ui_thread;
// Switch to a background thread
co_await winrt::resume_background();
if (auto storeContext{ winrt::Windows::Services::Store::StoreContext::GetDefault() })
{
const auto updates = co_await storeContext.GetAppAndOptionalStorePackageUpdatesAsync();
if (updates) {
const auto numUpdates = updates.Size();
if (numUpdates > 0) {
co_await ui_thread;
// This method must be called on the UI thread. See docs..
auto result = co_await storeContext.RequestDownloadAndInstallStorePackageUpdatesAsync(updates);
auto overallState = result.OverallState();
CString text;
switch (overallState)
{
case StorePackageUpdateState::OtherError:
text = L"Updates: Other Error";
break;
case StorePackageUpdateState::Downloading:
text = L"Updates: Downloading";
break;
case StorePackageUpdateState::Pending:
text = L"Updates: Pending";
break;
case StorePackageUpdateState::Canceled:
text = L"Updates: Cancelled";
break;
case StorePackageUpdateState::Deploying:
text = L"Updates: Deploying";
break;
default:
text.Format(L"Updates: %d", overallState);
break;
}
::PostMessage(hWnd, WM_USER_APP_MSG, 0, (LPARAM)new CString(text));
co_return;
}
}
}
}
catch (winrt::hresult_error const& ex)
{
// Handle WinRT exceptions
::PostMessage(hWnd, WM_USER_APP_MSG, 1, (LPARAM)new CString(ex.message().c_str()));
}
catch (std::exception const& ex)
{
// Handle other exceptions
::PostMessage(hWnd, WM_USER_APP_MSG, 1, (LPARAM)new CString(ex.what()));
}
}