C# 创建System.Windows.Controls.Image会引发异常-如何使用dispatcher来实例化它?

C# 创建System.Windows.Controls.Image会引发异常-如何使用dispatcher来实例化它?,c#,wpf,unit-testing,dispatcher,C#,Wpf,Unit Testing,Dispatcher,我正在一段代码上运行单元测试,该代码在测试中执行以下操作: Assert.IsNotNull(target.Icon); 在Icon属性的getter中,我执行以下操作: System.Windows.Controls.Image img = new System.Windows.Controls.Image(); 这引发了这个异常:System.InvalidOperationException:调用线程必须是STA,因为许多UI组件都需要它 我明白这意味着什么,我也明白我需要使用Disp

我正在一段代码上运行单元测试,该代码在测试中执行以下操作:

Assert.IsNotNull(target.Icon);
在Icon属性的getter中,我执行以下操作:

System.Windows.Controls.Image img = new System.Windows.Controls.Image();
这引发了这个异常:System.InvalidOperationException:调用线程必须是STA,因为许多UI组件都需要它

我明白这意味着什么,我也明白我需要使用Dispatcher,但我对如何或为什么。。。这是我的ViewModel的一个属性,在运行应用程序时,我不会遇到任何异常


其他信息:这仅在我升级到.NET 4时开始失败。

您是否使用任何其他非UI线程?如果是,您确定他们不访问此属性吗?检查您在框架中使用的组件是否使用线程或异步运行(如FileSystemWatcher),这些组件可能使用此属性。但是,更多的代码会有所帮助。

运行单元测试的线程不是STA线程,您可以创建如下STA线程:

Thread backgroundThread;
backgroundThread = new Thread(DoWork);
backgroundThread.SetApartmentState(ApartmentState.STA);
backgroundThread.Start();
我不知道您使用的是什么单元测试框架以及如何更改它的线程模型,但您需要在Thread之前调用Thread.SetApartmentState

“单元状态”是COM的东西,它是WPF所需要的,因为(正如错误所说)许多WPF控件都需要COM,STA线程不会自动有一个与之关联的调度程序

通常您不需要担心调度器,如果需要,系统将创建一个调度器


如果您确实需要为线程创建一个调度程序,您可以只读取
Dispacher.CurrentDispacher
——但是您将无法使用该调度程序执行任何有意义的操作,除非您让它控制线程(通过调用Dispacher.Run).

这里的问题是,您正在对WPF进行单元测试,这需要STA才能正常运行,但单元测试框架正在使用MTA。您需要设置单元测试框架以在STA中运行测试

每个框架都有不同的实现方式。通常,您只需在google中键入测试框架名称和STA即可找到它

  • 努尼特:

    • 我认为您可能需要稍微改变一下方法。我认为您需要做的是修改ViewModel,以便公开图像的URI,而不是图像控件


      在单元测试中,您将能够验证图像源是否设置为正确的位置,并且在UI中,您只需要将图像控件的源数据绑定到URI。

      理想情况下,是的,但在本例中,我的ViewModel根据某些属性从两个不同的位图动态生成图像对象。它不是硬编码到URL。是的,就是这样(我用的是NUnit,太完美了!)