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