作为我的应用程序迁移到 .NET 4 的一部分,我正在努力让一些 WPF 单元测试再次与 TeamCity 一起工作。
在以某种方式使用 WPF 控件(例如 ListItem)的所有测试中,我得到了一个以前没有得到的异常:
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
我明白是什么意思,查了之后发现我的线程确实是MTA,不是STA。
我的问题是我不知道如何解决这个问题,以及这个问题可能来自哪里......它是 TeamCity 的设置吗?规格?再一次,它在我切换到 .NET 4 之前有效。
我尝试了许多不同的解决方案,但没有任何效果。
我也有点困惑,之前没有人报告过这个(使用我特定的 TeamCity + MSpec + WPF 测试堆栈),这可能意味着我在某处做错了什么。
如果你有线索,请告诉我!
完全例外:
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
at System.Windows.Input.InputManager..ctor()
at System.Windows.Input.InputManager.GetCurrentInputManagerImpl()
at System.Windows.Input.KeyboardNavigation..ctor()
at System.Windows.FrameworkElement.EnsureFrameworkServices()
at System.Windows.FrameworkElement..ctor()
at System.Windows.Controls.Control..ctor()
at MyCompany.Dashboard.Client.Plugins.Common.Controls.Grids.CashflowGrid.ViewModel.ConfigureViewModel.CreateItem(String name) in d:\Program Files\JetBrains\BuildAgent2\work\6dd9af6ae2f9bbb9\Code\Src\MyCompany\Dashboard\Client\Plugins\Common\Controls\Grids\CashflowGrid\ViewModel\ConfigureViewModel.cs:line 171
at MyCompany.Dashboard.Client.Plugins.Common.Controls.Grids.CashflowGrid.ViewModel.ConfigureViewModel.Initialise(Type type, IList`1 currentSelection, Action`1 selectionChangedCallback) in d:\Program Files\JetBrains\BuildAgent2\work\6dd9af6ae2f9bbb9\Code\Src\MyCompany\Dashboard\Client\Plugins\Common\Controls\Grids\CashflowGrid\ViewModel\ConfigureViewModel.cs:line 37
at UnitTests.Plugins.Common.Controls.Grids.CashflowGrid.ViewModel.when_some_items_are_selected_on_the_chosen_list.<.ctor>b__1() in d:\Program Files\JetBrains\BuildAgent2\work\6dd9af6ae2f9bbb9\Code\Src\UnitTests.Plugins.Common\Controls\Grids\CashflowGrid\ViewModel\ConfigureViewModelTests.cs:line 82
对于这个异常,代码只是试图实例化一个 ListBoxItem,没什么特别的,但是在 MTA 线程上这样做会破坏它。
我尝试了什么:
将当前线程设置为 STA
Thread.CurrentThread.SetApartmentState(ApartmentState.STA)
它当然不起作用,因为它只有在线程开始之前才有可能
在初始化为 STA 的单独线程中运行代码:非常复杂,因为由于 MSpec 的性质,不同的方法在不同的时间被调用,所以你不能在同一个线程下运行所有东西。更准确地说,您不能在与“因为”语句相同的线程上运行“建立上下文”。
使用 STAThread 属性...是的,但在哪里?在我尝试过的任何地方都没有工作过
失败测试示例:
public class StaTestExample
{
Establish context = () => _control = new ListBox();
It should_not_be_null = () => _control.ShouldNotBeNull();
protected static Control _control;
}