この質問を書くことで解決したい問題がありますが、そうでない場合は投稿して、誰かが助けてくれるかどうかを確認します.
HTTP を介した COMET スタイルのロング ポーリングを利用するリアルタイム チャット サーバーとやり取りするために、クライアント ライブラリ (書き方が悪いと感じます) を使用しています。特定の状況でロング ポールをキャンセルする際に問題が発生し、同時実行処理コードを追加する必要があるのではないかと考えていますが、以下の理由により、これを行う最善の方法を見つけるのが難しいと感じています。
サブスクライブ コード(ロング ポールを開始する) は、次の大きなループとして実装されます。
doLongPoll()
{
while(true)
}
//IF channel field boolean unsubscribe == TRUE, if so BREAK;
//perform GET request (and store channel HTTPClient used for this call)
//remove HTTPClient used for this call
//IF channel field boolean unsubscribe == true, if so BREAK;
//IF connection problem sleep(1500) then CONTINUE
//post received data to listeners
}
}
登録解除の呼び出し(別のスレッドで呼び出される)
unsubscribe()
{
//set channel field boolean unsubscribe == FALSE
//get channel HTTPClient and shutdown
}
操作がインターリーブしている問題のケースを特定しました。私には、これはコードがマルチスレッドであり、クライアント コードがスレッド セーフでないことが原因のようです。また、管理が不十分で再利用されてhttpClient
いないことも役に立ちません。
私が抱えている問題の 1 つは、unsubscribe 呼び出しが次の getRequest の実行を停止しない場所の下にあります。
THREAD 1 (polling) THREAD 2
-------- --------
do unsubscribe check (pass)
unsubscribe called
set unsubscribe = true
check if httpClient saved (none)
perform getRequest (save HttpClient first)
この問題への最善のアプローチが何であると人々が考えているかを知りたいです(時間も限られているので、コードをあまり書き直すことはできません!)
これを修正するには、スレッド 1 の最初の登録解除チェックから、実際の get 要求が実行される直前に保存されるまでの同期ブロックを使用し、同じロックを使用して登録解除メソッドを同期できると考えました。httpClient
言及された最初の同期ブロックが 1 つのメソッド呼び出しで開始され、(lib の記述方法により) メソッド呼び出しチェーンのさらに下で終了するため、これは現時点では実用的ではありません。
または、リクエストごとではなくチャネルごとに1つhttpClient
作成するだけで、常にシャットダウンすることができ、同期を無視する可能性があります(私は思います)。
または、以下で提案されているように、同じ目的で割り込みを使用できます
どんな提案でも大歓迎です - 進展があれば編集します!
ありがとう