作为我的应用程序迁移到。net 4的一部分,我正在努力使一些WPF单元测试再次与TeamCity一起工作。
在所有以某种方式使用WPF控件(例如listtitem)的测试中,我得到了一个以前没有得到的异常:
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
我明白这是什么意思,经过检查,原来我的线程确实是MTA,而不是STA。
我的问题是,我不知道如何解决这个问题,以及这个问题可能来自哪里…这是否是TeamCity的游戏背景?MSpec吗?同样,在我切换到。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 FilesJetBrainsBuildAgent2work6dd9af6ae2f9bbb9CodeSrcMyCompanyDashboardClientPluginsCommonControlsGridsCashflowGridViewModelConfigureViewModel.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 FilesJetBrainsBuildAgent2work6dd9af6ae2f9bbb9CodeSrcMyCompanyDashboardClientPluginsCommonControlsGridsCashflowGridViewModelConfigureViewModel.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 FilesJetBrainsBuildAgent2work6dd9af6ae2f9bbb9CodeSrcUnitTests.Plugins.CommonControlsGridsCashflowGridViewModelConfigureViewModelTests.cs:line 82
对于这个异常,代码只是试图实例化一个ListBoxItem,没有什么特别的,但是在MTA线程上这样做会破坏它。
What I tried:
设置当前线程为STA
Thread.CurrentThread.SetApartmentState (ApartmentState.STA)
这当然不工作,因为它只可能在线程启动之前
在初始化为STA的单独线程中运行代码:非常复杂,因为由于MSpec的性质,不同的方法在不同的时间被调用,所以你不能在同一个线程下运行所有的东西。更准确地说,你不能在与"Because of"语句相同的线程上运行"Establish context"。
使用statthread属性…是的,但是在哪里?我从未在任何地方工作过试着
失败的测试示例:
public class StaTestExample
{
Establish context = () => _control = new ListBox();
It should_not_be_null = () => _control.ShouldNotBeNull();
protected static Control _control;
}
现在可以运行了
但问题是我们无法解释它。它仍然在另一个构建服务器上失败,但我们不关心这个。
如果有人遇到这个问题,下面是我们所做的:
- 禁用测试覆盖
- 禁用MSPec任务:构建变为绿色
- 重新启用覆盖和MSpec:它工作…
奇怪的是,确切的进程被应用在不同的构建服务器上(一个我们不再使用的旧服务器),它仍然失败。
我们想不出有什么别的变化
所以这有点神秘…我希望它不会回来咬我们!