Consider the following demo code attached to a button on a Windows Form:
private void button1_Click(object sender, System.EventArgs e)
{
var semaphore = new SemaphoreSlim(0, 1);
Invalidate(); // <-- posts a message that surprisingly will be processed while we're waiting
Paint += onPaint;
semaphore.Wait(1000);
Paint -= onPaint;
void onPaint(object s, PaintEventArgs pe)
{
throw new System.NotImplementedException(); // we WILL hit this!
}
}
Although we are hanging on a semaphore wait on the UI thread, the paint message posted by Invalidate()
will still be executed while we're hanging on the Wait()
- AND (of course) on the UI thread.
This demonstrates the root cause for a bug which I'm trying to create a failing Unit Test for - without using any Windows Form. I've been playing with custom SyncronizationContext
s and TaskScheduler
s for a few hours now but I have not been able to make this happen on the same thread.
What I would like to do, in pseudo code, would be something like:
[Test]
public void Test()
{
// something magic - this doesn't help:
// SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext());
SynchonizationContext.Current.Post(MethodToBeExecutedWhileWeAreWaitingAndOnThisVeryThread);
var semaphore = new SemaporeSlim(0, 1);
AssertThatMethodHasNotBeenCalled();
semaphore.Wait(1000);
AssertThatMethodGotCalled();
}