アプリを.NET4に移行する一環として、WPF単体テストの一部をTeamCityで再び機能させるのに苦労しています。
どういうわけかWPFコントロール(たとえばListItem)を使用しているすべてのテストで、以前は取得しなかった例外が発生します。
System.InvalidOperationException: The calling thread must be STA, because many UI components require this.
私はそれが何を意味するのかを理解しています、そしてチェックした後、私のスレッドは確かにSTAではなくMTAであることがわかりました。
私の問題は、これを修正する方法と、この問題がどこから発生するのかがわからないことです...それはTeamCityの設定ですか?MSpec?繰り返しになりますが、.NET4に切り替える前は機能していました。
私は多くの異なる解決策を試しましたが、何もうまくいきませんでした。
また、(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の性質上、異なるメソッドが異なる時間に呼び出されるため、同じスレッドですべてを実行することはできないため、非常に複雑です。より正確には、「Becauseof」ステートメントと同じスレッドで「Establishcontext」を実行することはできません。
STAThread属性を使用します...はい、しかしどこですか?私が試したどこでも働いたことはありません
失敗したテストの例:
public class StaTestExample
{
Establish context = () => _control = new ListBox();
It should_not_be_null = () => _control.ShouldNotBeNull();
protected static Control _control;
}