0

私はこの状況を持っています:

void foo::bar()
{
    RequestsManager->SendRequest(someRequest, this, &foo::someCallback);
}

RequestsManager は非同期で動作します。

  • SendRequest はリクエストをキューに入れ、呼び出し元に返します
  • 他のスレッドはキューからリクエストを取得して処理します
  • 1 つのリクエストが処理されると、コールバックが呼び出されます

SendRequest と同じスレッドで foo::someCallback を呼び出すことは可能ですか? そうでない場合、次の「コールバック制限」を回避するにはどうすればよいですか。コールバックは、リクエストマネージャーのブロックを回避するために時間のかかる操作を行うべきではありません。

4

3 に答える 3

3

いいえ - 呼び出し/コールバックはスレッド コンテキストを変更できません - スレッド間で通信するには何らかのシグナルを発行する必要があります。

通常、「someCallback」は、「SendRequest」呼び出しを開始したスレッドが待機しているイベントを通知するか (同期呼び出し)、SendRequest を (おそらくその処理の結果として) キューにプッシュします。 「SendRequest」呼び出しを開始したスレッドが最終的に pop します (非同期)。発信者がどのように信号を送るかによって異なります..

Aynch の例 - コールバックは PostMessage/Dispatcher.BeginInvoke で完了した SendRequest を GUI スレッドに呼び出し、結果を表示します。

于 2012-08-14T10:59:19.720 に答える
1

「時間のかかる操作」の定義によります。

これを行う古典的な方法は次のとおりです。

  • リクエストが処理されるとき、 はRequestManager それを実行する必要があります&foo::someCallback
  • リクエスト マネージャーをブロックしないようにするには、このコールバック内でフラグを立てます。
  • 呼び出されたスレッド内でそのフラグを定期的にチェックしますRequestsManager->SendRequest
  • このフラグはただのvolatile bool内側になりますclass foo

foo呼び出し元のスレッド (の) がすぐに処理されたことを確実に理解したい場合はrequest、追加の同期が必要です。

これらのスレッド間でブロッキング パイプを実装 (または既に実装されているものを使用) (またはシグナル/イベントを使用) します。アイデアは次のとおりです。

  • fooのスレッドが実行されますSendRequest
  • foo一部でスリープを開始しますselect(たとえば)
  • RequestManagerリクエストを実行し、次のことを行います。
    • 通話&foo::someCallback
    • のスレッドを「目覚めさせる」((を使用して)スリープしfooているファイル記述子に何かを送信することにより)fooselect
  • foo目覚めている
  • volatile boolすでに処理されたリクエストのフラグをチェックします
  • やるべきことをする
  • フラグを無効にします
于 2012-08-14T11:01:46.657 に答える
1

それを達成する方法はいくつかあります。

A) シグナル処理と同様の戦略を実装する

リクエスト処理が終了するRequestManagerと、待機リストにコールバック呼び出しが置かれます。次回SendRequestが呼び出され、実行を返す直前に、スレッドの保留中のコールバックがあるかどうかを確認して実行します。これは、クライアントの要件が最小限の比較的単純なアプローチです。遅延が問題にならない場合は、これを選択してください。RequestManager保留中のコールバックを強制的にチェックする API を公開できます

B) コールバック対象のスレッドを中断し、3 番目のスレッドでコールバックを実行する

これにより、すべての注意事項を備えた真の非同期ソリューションが得られます。ターゲットスレッドの実行が中断され、実行が割り込みハンドラにジャンプしたように見えます。コールバックが戻る前に、ターゲット スレッドを再開する必要があります。コールバック内からスレッド ローカル ストレージまたは元のスレッドのスタックにアクセスすることはできません。

于 2012-08-14T11:04:19.497 に答える