等待信号量可能仍在同一线程上执行代码

Dan*_*röm 5 c# multithreading semaphore winforms synchronizationcontext

考虑附加到 Windows 窗体上的按钮的以下演示代码:

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!
    }
}
Run Code Online (Sandbox Code Playgroud)

尽管我们挂在 UI 线程上的信号量等待上,但是Invalidate()当我们挂在Wait()UI 线程上的- AND(当然)上时,仍然会执行由 发布的绘制消息。

说明了我试图为其创建失败的单元测试的错误的根本原因 - 不使用任何 Windows 窗体。我已经使用 custom SyncronizationContexts 和TaskSchedulers玩了几个小时,但我无法在同一线程上实现这一点。

我想用伪代码做的是:

[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();
}
Run Code Online (Sandbox Code Playgroud)