Consider:
async Task FooAsync()
{
await BarAsync().ConfigureAwait(false);
UpdateUI(); // Bug
}
I'm looking for a way to systematically ensure this doesn't happen.
Perhaps a naming convention, where methods that must be run on the UI thread get a special suffix. Or static checking, where an [UIThreadOnlyAttribute] on a method means that any caller must have that same attribute, and may not call ConfigureAwait(false).
Any suggestions?
As long as your application is layered reasonably, it shouldn't be an issue.
UI layer (e.g., event handlers) and the logical UI layer (e.g., ViewModel) require a UI context and should not use ConfigureAwait. Other layers should use ConfigureAwait. That's a simple guideline that has worked well for me.
As a sanity check, at the beginning of the UpdateUI method you can manually verify whether the current thread has the proper synchronization context. For a WinForms app, it could look like this:
void UpdateUI()
{
Debug.Assert(SynchronizationContext.Current is WindowsFormsSynchronizationContext);
// ...
// Do the actual UI update
}
For a WPF app, the first line would be:
Debug.Assert(SynchronizationContext.Current is DispatcherSynchronizationContext);
That works for me.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With