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)