STAThread 対 MTAThread (WHorst)

最近遭遇したスレッドの問題を皆さんにご紹介しましょう。私と同じ目に遭う人を減らせるかもしれません。

ここで、だれかが書いた C# アプリケーションを例とし、ここでは "DeltaEngine" と呼ぶことにします。DeltaEngine はネイティブ アセンブリを呼び出し、そこから特定のイベントを処理します。

DeltaEngine をライブラリ プロジェクトとして参照するソリューションを作成し、VB プロジェクトからこのプロジェクトを呼び出しました。このプロジェクトの名前を "VBApp" とすると、参照構造は次のようになります。

VBApp (VB) -> DeltaEngine (C#) -> NativeCode

VBApp をスタートアップ プロジェクトとして使用してソリューションを実行したとき、ネイティブ コードから DeltaEngine がイベントを取得するのをいつまでも待たされました。しかし、DeltaEngine をスタートアップ プロジェクトとしてまったく同じ呼び出しを実行した場合、予想どおりにイベントを処理することがわかりました。この問題を解決するために長時間を費やしたあげく、お手上げとなったのです。

最終的に、C# プロジェクトは既定でマルチ スレッド アパートメント (MTA) を使用するのに対し、VB プロジェクトは既定でシングル スレッド アパートメント (STA) を使用することを人から指摘されました。DeltaEngine はもともと C# プロジェクトのスタートアップ アプリケーションとして作成されたため、MTA スレッドを前提としていたのです。VB スタートアップ プロジェクトからこのコードの呼び出しを開始したとき、それとは知らずに STA スレッドで実行していたわけです。これが原因で、DeltaEngine コードはイベントの発生後もイベントを待機し、いつまでも待機し続けることになってしまいました。DeltaEngine をスタートアップ プロジェクトとして設定して、同じ呼び出しを実行すると、MTA スレッドを使用するために予想どおりに動作するのです。

解決方法は、VBApp の Sub Main に MTAThreadAttribute を追加することでした。その後は正常に動作するようになりました。

<MTAThread> Sub Main()

同様に、STAThread 属性を C# の Main メソッドで使用する場合、コードは次のようになります。

[STAThread]

static void Main()

Windows フォームは STA スレッドを必要とするため、C# Windows アプリケーションを作成する場合、このようなコードを Program.cs に使用することになります。

STAThread および MTAThread に関するドキュメントは既存のものがあるので、詳細については次のリンクのドキュメントを参照してください。

STAThreadAttribute

https://msdn2.microsoft.com/ja-jp/library/system.stathreadattribute(VS.71).aspx

https://blogs.msdn.com/jfoscoding/archive/2005/04/07/406341.aspx (英語)

MTAThreadAttribute

https://msdn2.microsoft.com/ja-jp/library/system.mtathreadattribute(VS.71).aspx

- VB IDE テスト、Bill Horst

VB チーム

投稿 : 2008 年 3 月 24 日 12:47 PM

分類 : Bill Horst

VB チームの Web ログ - https://blogs.msdn.com/vbteam/archive/2008/03/24/stathread-vs-mtathread-whorst.aspx (英語) より