6

WPF および/または Winforms クライアントによって使用されているライブラリがあります。

次のような非同期メソッドを提供しています。

Task<int> GetIntAsync()

(残念ながら) 同期ラッパー メソッドも提供しています。

int GetInt();

基本的に、非同期メソッドを呼び出し.Resultてそのタスクを呼び出すだけです。

最近、特定の状況下で、一部のコードをGetIntAsyncメイン UI スレッドで実行する必要があることに気付きました (「シングル」スレッド モデルとしてマークされたレガシー COM コンポーネントを使用する必要があります (つまり、コンポーネントは、メイン STA スレッドだけでなく、メイン STA スレッドで実行する必要があります)。スタスレッド)

したがって、問題はGetInt()、メインスレッドで呼び出されるとデッドロックになることです。

  • .Resultメインスレッドをブロックし、
  • 内のコードGetIntAsync()Dispatcher.Invoke、メイン スレッドでの実行を試みます。

同期メソッドは既に使用されているため、これを削除することは重大な変更になります。その代わりに、同期メソッドでWaitWithPumpingGetInt()を使用して、メイン スレッドの呼び出しを機能させることを選択しました。

GetInt()これは、UI コードから使用するクライアントを除いて正常に機能します。以前は、 を使用GetInt()すると UI が応答しなくなると予想していました。つまりGetInt()、ボタンのクリック イベント ハンドラー内から呼び出した場合、ハンドラーが戻るまで Windows メッセージが処理されないと予想していました。メッセージがポンピングされ、UI応答し、同じボタンをもう一度クリックできるようになりました (おそらく、ハンドラーを再入可能にコーディングしていませんでした)。

合理的な解決策がある場合、クライアントが呼び出し中に応答する UI に対してコーディングする必要がないようにしたいと考えています。GetInt

質問:

  • WaitWithPumping「Invoke to main」メッセージをポンピングするが、他の UI 関連メッセージをポンピングしない方法はありますか?
  • クライアント UI がモーダル ダイアログが現在表示されているかのように動作し、非表示になっている場合 (つまり、ユーザーが他のウィンドウにアクセスできない場合) で十分です。しかし、私が読んだところによると、モーダル ダイアログを非表示にすることはできません。
  • あなたが考えることができる他の回避策をいただければ幸いです。
4

1 に答える 1

4

既存のメッセージ ポンプを利用する代わりに、 のコンテキスト内で独自のメッセージ ポンプを作成できますGetInt。 書き方についてのブログ記事は こちらです。これは、ブログが作成する完全なソリューションです。

それを使用すると、次のように記述できます。

public int GetInt()
{
    return AsyncPump.Run(() => GetIntAsync());
}

これにより、期待どおりに UI スレッドが完全にブロックされGetIntAsyncますが、別のSynchronizationContext. また、このメッセージ ポンプはまだメインの STA/UI スレッドで実行されていることに注意してください。

于 2013-02-11T20:59:52.110 に答える