我在上周尝试过其他SO问题的各种方法,这是我发现的最佳方法,但我不知道如何用NUnit进行单元测试。
private void VerifyDispatcherThread()
{
var context = SynchronizationContext.Current;
if (context != null && context is DispatcherSynchronizationContext)
{
Log.For(this).Info("WARNING! - Method Should Not Be Called From Dispatcher Thread.");
if (DispatcherThreadSafetyEnabled)
{
throw new ThreadStateException("Method Should Not Be Called From Dispatcher Thread.");
}
}
}
这是我们的测试(不工作)
[Test]
public void Should_throw_exception_when_called_from_dispatcher()
{
// Arrange
var called = false;
Boolean? success = null;
var httpClient = new HttpClient(HttpTimeOut);
// This emulates WPF dispatcher thread
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext());
Dispatcher dispatcher = Dispatcher.CurrentDispatcher;
// Act
dispatcher.BeginInvoke(delegate()
{
try
{
ConfigurationManager.AppSettings.Set("DispatcherThreadSafetyEnabled", "true");
httpClient.Post("http://Foo", "content xml");
success = true;
}
catch
{
success = false;
}
finally
{
ConfigurationManager.AppSettings.Set("DispatcherThreadSafetyEnabled", "false");
}
called = true;
});
// this part is a bit ugly
// spinlock for a bit to give the other thread a chance
var timeout = 0;
while (!called && timeout++ < 1000)
Thread.Sleep(1);
// Assert
Assert.IsNotNull(success, "Method was never invoked");
Assert.IsFalse(success.Value, "Expected to fail");
}
DispatcherThreadSafetyEnabled是我们的app.config设置,因此我们只能切换日志记录或抛出异常。
我们要做的是验证调用方法在调用时不使用GUI线程。它似乎正在工作,但我们正在努力进行单元测试。
这里希望有人这样做,可以帮助我们应对挑战。
答案 0 :(得分:1)
当前 SynchronizationContext
由不同的框架(Winforms,WPF等)设置为不同的实现。
引自this MSDN文章:
WindowsFormsSynchronizationContext(System.Windows.Forms.dll: System.Windows.Forms)Windows窗体应用程序将创建并安装一个 WindowsFormsSynchronizationContext作为任何的当前上下文 创建UI控件的线程。
DispatcherSynchronizationContext(WindowsBase.dll: System.Windows.Threading)WPF和Silverlight应用程序使用 DispatcherSynchronizationContext,将委托排队到UI thread的Dispatcher具有“Normal”优先级。这个 当a时,SynchronizationContext作为当前上下文安装 线程通过调用Dispatcher.Run开始其Dispatcher循环。
由于您只测试非空和SynchronizationContext
的类型,请尝试通过从单元测试中调用SynchronizationContext
将当前DispatcherSynchronizationContext
设置为SynchronizationContext.SetSynchronizationContext
的实例。示例代码如下:
SynchronizationContext.SetSynchronizationContext(new DispatcherSynchronizationContext(Dispatcher.CurrentDispatcher));
请注意,这不是Winforms / WPF应用程序中推荐的。