2011-02-10 8 views
11

これは「これは可能なのですか?オンラインでは見つけられないので、私に簡単な例を教えてください。一種の質問。.NET 4タスク並列ライブラリはCOMオブジェクトを使用できますか?

私は、C#を使用している.NET Framework 4のTask Parallelライブラリを使用して並列に実行したい、完全に分離した(つまり、恥ずかしい並列の)プロセスがいくつかあります。これらのプロセスの中には、COM/OLEの自動化を介してアクセスできるソフトウェアの使用が必要なものがあります。

特に、Parallel.Foreach内の別の関数を呼び出して処理を処理するため、項目のリストからタスクを分割するParallel.Foreach()ループがあります(これらの関数のいくつかはCOMライブラリを使用して作業)。

これは可能ですか?ありがとう。

+4

すぐに試してみてください...試してみてください。 – Oded

答えて

18

TPLでCOMオブジェクトを使用することは100%可能です。デフォルトでは、TPLは標準の.NET ThreadPoolを使用しますが、TPLには拡張ポイントがthe TaskScheduler classであり、作成したスレッドに作業をディスパッチできる独自のスケジューラを提供できます。

COMオブジェクトを使用する場合、まずCOMクラスにSTAスレッドまたはMTAスレッドが必要かどうかを知る必要があります。 MTAスレッディングの場合、COMクラスは任意のランダムスレッドから既に使用できるため、実行する必要のある特別なことはありません。残念ながら、最も古典的なCOMオブジェクトはSTAスレッディングに頼っている傾向があります。その場合は、TaskSchedulerというカスタムを使用する必要があるため、使用している.NETスレッドがinitialized as an STA compatible threadになるようにします。

TaskSchedulersは、書くのが簡単ではありませんが、スレッドの基本的な知識があれば、どちらでも書くのは難しくありません。幸いにもthe ParallelExtensions Extras libraryはすでにStaTaskSchedulerクラスを提供していますので、あなた自身で何かを書く必要はありません。 PFXチームのa great blog post hereには、StaTaskSchedulerクラスの実装といくつかの使用例が記載されています。

基本的には、新しいStaTaskSchedulerを静的にクラスのどこかで初期化してから、そのインスタンスでスケジュールされていることを指定してTasksを開始するだけです。これは次のようになります:

// Create a static instance of the scheduler specifying some max number of threads 
private static readonly StaTaskScheduler MyStaTaskScheduler = new StaTaskScheduler(4); 

.... 

// Then specify the scheduler when starting tasks that need STA threading 
Task.TaskFactory.StartNew(
() => 
{ 
    MyComObject myComObject = new MyComObject(); 

    myComObject.DoSomething(); 

    // ... etc ... 
}, 
CancellationToken.None, 
TaskCreationOptions.None, 
MyStaTaskScheduler); 
+0

非常に興味深い、私はこれを調べなければならないでしょう、ありがとう!参考までに、私が達成しようとしている主な機能は、R(http://www.r-project.org/)のいくつかのワークフローの並列実行です。私が何かを見つけたら、ここに報告します。 – user483679

+0

ありがとう、ちょうど私が必要としたもの。 –

2

可能性はありますが、機能しない可能性もあります。

多くのCOMオブジェクトには、特定のapartment threadingが必要です。 Parallel.For/ForEachを使用すると、アパートメントスレッド設定がない.NET ThreadPoolで実行されています。これはうまくいくかもしれませんし、いくつかのCOMオブジェクトのためにすることができますが、追跡が困難なクラッシュや奇妙なCOM例外を引き起こす可能性があります。

0

私はまだ確認していませんが、参考になるかもしれないいくつかの追加情報です。既定のタスクスケジューラは、現在のスレッドを使用して作業の一部を行い、必要に応じてスレッドプールから追加のスレッドを追加します。

Parallel.ForEachを実行しているときにCOMオブジェクトを共有していると、この問題が発生する可能性があります。たとえば、メインスレッドがSTAであるとします。 COMオブジェクトをインスタンス化し、Parallel.ForEachを使用して、各スレッドが以前にインスタンス化されたCOMオブジェクトにアクセスしようとする作業を行います。私はそれが壊れると思うし、最初のテストはこれを裏付けるようだ。このシナリオでは、少なくとも2つのオプションがあります。

  • COMオブジェクトがMTAをサポートしていると仮定すると、呼び出しスレッドはMTAを使用しているとします。しかし、これは他の理由では選択肢ではないかもしれません。たとえば、アプリケーションがWindowsフォームアプリケーションの場合、Main()にはSTAThread属性が必要です。
  • Drewが言及したStaTaskSchedulerなどの代替タスクスケジューラを使用します。すべてのSTAスレッドを持つか、呼び出しスレッドを使用せず、すべてのMTAスレッドを実行するスケジューラを使用することができます。
関連する問題