I have some async library methods where it is important the ConfigureAwait(false)
be used "all the way down". I'd like to write an NUnit test that verifies that this is so. How can I do that? I imagine that I'd have to somehow hijack the synchronization context with a custom implementation?
ConfigureAwait(false) involves a task that's already completed by the time it's awaited (which is actually incredibly common), then the ConfigureAwait(false) will be meaningless, as the thread continues to execute code in the method after this and still in the same context that was there previously.
In this video we answer the ever popular question “Which do I use, ConfigureAwait True or False?”. The direct answer to this question is: – If you are a writing code for the UI, use ConfigureAwait(true).
ConfigureAwait(false) is about not returning back to the synchronization context when an awaiter completes. It's about performance, not deadlocks.
To improve performance and avoid potential deadlocks, use ConfigureAwait(false) in any non-UI code. The exception here is app-level code, such as Windows Forms, WPF, and ASP.NET. ConfigureAwait(true) corresponds to the default behavior and does nothing meaningful, therefore such calls can be safely omitted.
I don't think this is possible. You could create a custom synchronization context (see striked answer below), but it would only check the first awaited call. If the first awaited call called uses ConfigureAwait(false)
, the continuation will run on a different thread, which won't have a SynchronizationContext
, so it won't be possible to check whether subsequent async calls use ConfigureAwait(false)
or not.
Indeed, a custom synchronization context seems to be the only way. Here's a possible implementation:
class TestSynchronizationContext : SynchronizationContext
{
public bool PostCalled { get; private set; }
public override void Post(SendOrPostCallback d, object state)
{
PostCalled = true;
base.Post(d, state);
}
public void Reset()
{
PostCalled = false;
}
}
You can then write your test like this:
[Test]
public void TestFoo()
{
var context = new TestSynchronizationContext();
SynchronizationContext.SetSynchronizationContext(context);
FooAsync().Wait();
Assert.IsFalse(context.PostCalled);
}
if PostCalled
is true, it means that the SynchronizationContext
's Post
method was called, which shouldn't happen if ConfigureAwait(false)
was used.
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