The C++/WinRT library provides the winrt::
function for resuming a coroutine on the foreground thread of a dispatcher. It supports three types of dispatchers: Windows.
, Windows.
, Microsoft.
.
But what happens if the thread switch fails? This happens if the dispatcher thread is no longer accepting new work, either because it is shutting down, or because it no longer exists at all.
If a CoreÂDispatcher
is unable to dispatch a work item, it silently releases the work item without executing it. For winrt::
, that means that your coroutine appears to hang. The resumption never happens, nothing in the coroutine executes beyond the co_await winrt::
, and your coroutine is leaked.
If either of the DispatcherÂQueue
objects is unable to dispatch a work item, then the TryÂEnqueue()
method returns false
. The winrt::
function propagates this return value as the return value of co_await
. This means that you are expected to check the return value to find out whether the thread switch is successful.
if (co_await winrt::resume_foreground(dispatcherQueue)) { // Yay, executing on the dispatcher thread } else { // Rats, was not able to switch threads }
In practice, nobody¹ checks the return value of co_await winrt::
, so the result is that the code continues running on the wrong thread. It thinks that it’s on the dispatcher thread, but it’s not.
This sure looks like a disaster. We’ll find an escape route next time.
¹ I have yet to find any code in any code base that checks the return value. Not even the C++/WinRT unit tests check the return value!
0 comments
Be the first to start the discussion.