次の方法で共有


Office でのスレッド処理のサポート

この記事では、Microsoft Office オブジェクト モデルでのスレッド処理のサポート方法について説明します。 Office オブジェクト モデルはスレッド セーフではありませんが、Office ソリューションで複数のスレッドを操作できます。 Office アプリケーションは、コンポーネント オブジェクト モデル (COM) サーバーです。 COM を使用すると、クライアントは任意のスレッドで COM サーバーを呼び出すことができます。 スレッド セーフではない COM サーバーの場合、COM には同時呼び出しをシリアル化するメカニズムが用意されているため、サーバー上で同時に実行される論理スレッドは 1 つだけです。 このメカニズムは、シングル スレッド アパートメント (STA) モデルと呼ばれます。 呼び出しはシリアル化されるため、サーバーがビジー状態の間、またはバックグラウンド スレッドで他の呼び出しを処理している間、呼び出し元が一定期間ブロックされる可能性があります。

適用対象: このトピックの情報は、ドキュメント レベルのプロジェクトと VSTO アドイン プロジェクトに適用されます。 「Office アプリケーションとプロジェクトの種類で使用できる機能」を参照してください。

複数のスレッドを使用する場合に必要な知識

複数のスレッドを操作するには、マルチスレッドの次の側面に関する少なくとも基本的な知識が必要です。

  • Windows API

  • COM マルチスレッドの概念

  • Concurrency

  • Synchronization

  • マーシャ リング

    マルチスレッドの一般的な情報については、「 マネージド スレッド」を参照してください。

    Office はメイン STA で実行されます。 この影響を理解することで、Office で複数のスレッドを使用する方法を理解できます。

基本的なマルチスレッド シナリオ

Office ソリューションのコードは、常にメイン UI スレッドで実行されます。 バックグラウンド スレッドで別のタスクを実行して、アプリケーションのパフォーマンスを滑らかにしたい場合があります。 目標は、1 つのタスクの後に続くタスクではなく、一見 2 つのタスクを一度に完了することです。その結果、実行がスムーズになります (複数のスレッドを使用する主な理由)。 たとえば、メインの Excel UI スレッドにイベント コードがあり、バックグラウンド スレッドで、サーバーからデータを収集し、Excel UI のセルをサーバーのデータで更新するタスクを実行できます。

Office オブジェクト モデルを呼び出すバックグラウンド スレッド

バックグラウンド スレッドが Office アプリケーションを呼び出すと、呼び出しは STA 境界を越えて自動的にマーシャリングされます。 ただし、バックグラウンド スレッドが呼び出しを行った時点で、Office アプリケーションが呼び出しを処理できる保証はありません。 いくつかの可能性があります。

  1. Office アプリケーションは、通話に入る機会を得るためにメッセージをポンプする必要があります。 その処理が中断せずに重い作業を続けている場合、これには時間がかかる可能性があります。

  2. 別の論理スレッドが既にアパートメント内にある場合、新しいスレッドは入力できません。 これは、多くの場合、論理スレッドが Office アプリケーションに入り、呼び出し元のアパートメントに再入可能なコールバックを行うときに発生します。 アプリケーションは、その呼び出しが返されるのを待ってブロックされます。

  3. Excel は、着信呼び出しをすぐに処理できない状態である可能性があります。 たとえば、Office アプリケーションでモーダル ダイアログが表示されている場合があります。

    可能性 2 と 3 では、COM は IMessageFilter インターフェイスを提供します。 サーバーが実装する場合、すべての呼び出しは HandleIncomingCall メソッドを 介して入力します。 可能性 2 の場合、呼び出しは自動的に拒否されます。 可能性 3 では、状況に応じて、サーバーは呼び出しを拒否できます。 呼び出しが拒否された場合、呼び出し元は何を行うかを決定する必要があります。 通常、呼び出し元は IMessageFilter を実装します。この場合、 RetryRejectedCall メソッドによって拒否が通知されます。

    ただし、Visual Studio の Office 開発ツールを使用して作成されたソリューションの場合、COM 相互運用機能は拒否されたすべての呼び出しを COMException に変換します ("アプリケーションがビジーであることを示したメッセージ フィルター")。 バックグラウンド スレッドでオブジェクト モデルの呼び出しを行う場合は常に、この例外を処理する準備をしておく必要があります。 通常、一定時間再試行してからダイアログを表示する必要があります。 ただし、バックグラウンド スレッドを STA として作成し、そのスレッドのメッセージ フィルターを登録してこのケースを処理することもできます。

スレッドを正しく起動する

新しい STA スレッドを作成するときは、スレッドを開始する前にアパートメントの状態を STA に設定します。 次のコード例は、これを行う方法を示しています。

System.Threading.Thread t = new System.Threading.Thread(AnObject.aMethod);

t.SetApartmentState(System.Threading.ApartmentState.STA);
t.Start();

詳細については、「 マネージド スレッドのベスト プラクティス」を参照してください

モードレス フォーム

モードレス フォームを使用すると、フォームの表示中にアプリケーションと何らかの種類の対話を行えます。 ユーザーはフォームを操作し、フォームは閉じずにアプリケーションと対話します。 Office オブジェクト モデルは、マネージド モードレス フォームをサポートしています。ただし、バックグラウンド スレッドでは使用しないでください。