次の方法で共有


Excel オブジェクト モデルに対する非同期プログラミングの制限

概要

Excel オブジェクト モデル (OM) へのインプロセス非同期プログラミングでは、エラーやアプリケーションの状態が正しくない可能性があります。  OM の直接非同期プログラミングはサポートされていません。

Excel オブジェクト モデルでは、マクロまたはアドイン ソリューションの非同期イベントから呼び出されたときにコンカレンシーまたは再入性の問題から自動的に保護されないため、呼び出し元は、非同期コールバック (タイマー イベントなど) やバックグラウンド スレッドから OM を呼び出す前に、このような条件をシリアル化して処理する必要があります。 最適な安全性を確保するために、このようなタスクはメイン スレッドがアイドル状態になるまで待機してから、新しいオートメーション タスクでユーザー アクティビティを中断することをお勧めします。 これを行う方法は、マクロ/アドインの種類、およびソリューションで使用されるプログラミング言語によって異なります。

詳細情報

Microsoft Excel では、開発者が Excel の動作を自動化および制御するために使用するプログラミング オブジェクト モデル (OM) をサポートしています。 OM はもともと Visual Basic for Applications (VBA) マクロ用に設計されていましたが、コンポーネント オブジェクト モデル (COM) アドイン、マネージド (.NET) アドイン、Visual Studio Tools for Office (VSTO) ドキュメント、アプリケーション レベルのカスタマイズ、その他のプロセス内拡張機能やコントロールなど、ほとんどのアドインの種類でも使用されています。

元の設計では、OM は、ユーザーがマクロを実行したり、マクロ/アドインに関連付けられた UI 要素をクリックしたり、Excel によって直接ユーザー定義ワークシート関数に対して呼び出されたり、外部コントローラーからのアプリケーション全体の自動化時に使用されたりする場合など、ユーザー アクションに基づいて OM が呼び出されることを前提に構築されています。  ユーザーが操作している間に Excel を自動化しようとすると、問題が発生し、プログラムを損なう可能性のあるエラーや状態の問題が発生する可能性があります。 ユーザーが操作しているときに Excel が処理する可能性があるさまざまなアクションと関数のため、その多くはマクロ/アドインの呼び出し、またはそのようなアドインを呼び出すことができる計算イベントにつながる可能性があるため、Excel では、ユーザー アクション (または計算) の実行中に OM 呼び出しを防止しません。  これを行うと、製品が最も柔軟な方法でマクロ/アドインを使用する能力に悪影響を与えます。  Excel は、ユーザーと OM 呼び出し元の間の同時アクティビティから保護するために最善を尽くしますが、マクロ/アドイン自体が導入するようなインスタンスから保護することはできません。

プログラムが Excel に対して非同期で実行される外部ソースから情報を取得し、OM を使用して Excel で何かを更新したり、Excel からデータを取得して非同期イベントの処理を決定したりする場合があります。   プログラムが、Excel が処理しない非ユーザー インターフェイス呼び出しアクション (タイマー コールバック、バックグラウンド スレッド上の直接イベント、または Excel に不明な外部ソースからの送信または投稿されたメッセージに応答する) から OM を使用しようとすると、その時点で OM が呼び出しを処理するための適切な状態になっていない可能性があります。 OM は呼び出しを妨げるものではなく、一部の呼び出しは機能するように見えますが、このアクションは危険です。  これにより、コンカレンシー エラーが発生したり、メイン スレッドに再入が発生したりする可能性があります。これにより、エラー、状態の問題、ブックの破損、アプリケーション例外 (クラッシュ) がプログラムに発生する可能性があります。

マクロ/アドイン デザイナーは、このようなプログラミング手法 (タイマー、et.al.) の使用を避けるか、Excel OM を使用する前にコンカレンシーと再入性の問題を防ぐために、そのようなコードを適切に処理するように注意する必要があります。 これらの問題から保護せずに OM に非同期プログラミングを使用することはサポートされておらず、このようなアクションによって引き起こされる破損やクラッシュは、Excel では "バグ" とは見なされません。 むしろ、マクロ/アドイン自体の設計上の欠陥と見なされます。これは、状況の下でコンカレンシーと再入性を導入するためです。そのため、コード内でのコンカレンシーと再入の防止が行われます。

この状況に関する警告は、もともと VBA OM と XLL C-API の両方の Excel 97 ソフトウェア開発キット (SDK) に記載されていました。  この制限は、プログラミング インターフェイスの導入以降、Excel のすべてのバージョンに適用されています。  製品が成長し、時間の経過と共に機能や機能が追加されるにつれて、同時または再入可能なアクションの可能性は、特定のタイムスライスに対して同じ相対的なワークロードの下で増加しています。  これにより、新しい問題と見なされる場合があります。実際には問題ではありません。 "以前は機能していた" コードは、この状況が発生した場合は有効ではありませんでした。むしろ、過去に "より少ない" 失敗をしただけなので、以前はあまり注目を集めませんでした。 ただし、開発者が非同期プログラミングを慎重に処理する責任を開発者に思い出させるために、この警告を再度発行しています。  Excel OM によって自動的に処理されるとは想定しないでください。

非同期情報を収集して使用する必要があり、他の手段を使用する余裕がない開発者は、OM を使用する前にコンカレンシーと再入可能な問題を処理するためにコードを保護している限り、それらを引き続き使用できる場合があります。  これを行うにはいくつかの方法があります。どの方法を使用するかは、マクロ/アドインの設計、使用されるプログラミング言語、および一般的なアーキテクチャによって異なります。 タイマー コールバックなど、より一般的なタスクについては、UserForm/WinForm/API タイマーではなく Application.OnTime 関数を使用することをお勧めします。 OnTime は、OM がユーザーが実行するタスクと競合しない新しいコマンドを受け入れる準備ができたら、メイン スレッド アイドル状態から呼び出されることを保証します。 外部非同期イベントに基づいてセルにデータを取り込む場合は、OM を使用する代わりに、Real-Time Data (RTD) API の使用を検討してください。  RTD も同様に、これらの問題がユーザーの対話を妨げることなく、正しく更新することが保証されています。   バックグラウンド スレッドを使用するマネージド コードは、OM に参加する前にメイン スレッドに委任する必要があります。  OM を使用する前に、WinForms MethodInvoker オブジェクトを使用して UI スレッドでデリゲート関数を実行することを検討してください。 これにより、エラーにつながる可能性のあるすべての条件が防止されるわけではありませんが、最悪のケースをカバーします。 完全な保護を得るために、ネイティブ コード コンポーネントをキューに入れたイベント コールバックに対して提案し、アイドル時にデリゲート コールバック関数を発生させます。  C/C++ プログラムは、アイドル状態のタスク処理を登録して、ユーザー アクティビティが存在しないときに実行するタスク アクションのプライベート キューを処理できます。

この警告は、マクロ/アドイン コードがモーダル状態でないときに発生する非同期イベントに応答している状況 (独自のダイアログが表示されている場合など) に適用されます。 そのため、マクロ/アドイン コードがメイン スレッドを制御している間に発生するタイマーやその他のイベントは、ここでは問題ありません。  コントロールが Excel に返された後にこのようなコールバックを取得しようとするケースのみです。  また、Windows システム イベント、OLE リンク更新プログラム、DDE リンク更新プログラム、RTD など、Excel 自体が処理する非同期イベントにも適用されません。