2

独自のカスタム作業ウィンドウを備えたVSTOアプリケーションレベルのアドインがあります。SelectionChangeイベントをインターセプトし、選択に関連する情報をカスタム作業ウィンドウに表示しようとしています。私はそれを同期的に行う方法を知っています。

ただし、表示する情報を取得するプロセスは遅く、情報を取得している間はアプリケーションをブロックしたくありません。さらに、ユーザーは選択を数回変更する可能性があり、これが発生した場合は、進行中の「フェッチ」操作をキャンセルしたいと思います。

長時間実行する操作を待ってみましたが、フォームを開いていないため、同期コンテキストが設定されていないため、試行するとすぐにInvalidOperationException(クロススレッド操作は無効)が発生します作業ウィンドウのコントロールを更新します。

async void Application_WindowSelectionChange(PowerPoint.Selection selection)
{
    var results = await MyLongRunningOperation(cancellationTokenSource.Token);

    myControl.Text = DescribeResults(results); // BOOM!
}

これを克服するための最良の方法は何ですか?選択が変更されたイベントハンドラーの先頭に次のように配置して、上記のリンクでStephenが提案したように実行してみました。

SynchronizationContext.SetSynchronizationContext(new WindowsFormsSynchronizationContext())

それはうまくいきませんでした。突然、他のすべてのイベントハンドラーが、「ハンドルが作成されるまでBeginInvokeを呼び出すことができない」というエラーが発生し始めました。オールオアナッシングの場合に備えて、すべてのイベントハンドラーの先頭に同じコードを配置してみました。それもうまくいきませんでした。おそらく、 1つの WindowsFormsSynchronizationContextオブジェクトを作成し、それをすべてのハンドラーに使用する必要がありましたが、今はストローをつかんでいることに気づいています。

それがうまくいかない場合は、他にどのようなアプローチを試す必要がありますか?まだ道はBeginInvokeありますか、それとも他の方法でUIスレッドにジャンプできますか?

4

1 に答える 1

2

突然、他のすべてのイベントハンドラーが、「ハンドルが作成されるまでBeginInvokeを呼び出すことができない」というエラーが発生し始めました。

それは不思議です。私もストローを握っていますが、これを試してみてください:

Control control = new Control();
IntPtr handle = control.Handle;

SynchronizationContext.SetSynchronizationContext直接呼び出す代わりに。各イベントの開始時にこれを行う必要がある場合があります。

(このブログエントリからのアイデア)。

于 2012-10-15T16:06:29.357 に答える