2013-08-29 2 views
9

WindowsでC++でApache Thriftを使用していますが、進行中のブロック読み取り操作のキャンセルについてお問い合わせしたいと思います。データが受信されるまで、読み取り操作(たとえば、TProtocol :: readByte)はブロックされます。別のスレッドからトランスポートを閉じると、ヌルポインタに関するアサーションに失敗します。Thriftでブロック読み取り操作をキャンセルする

ブロックされた読み取り操作をキャンセルする他の方法はありますか?

答えて

3

ブロックモードを使用している場合、読み取り操作を中止する唯一のオプションは、読み取り前にTSocketでタイムアウトに設定されています。

+0

この場合、TProtocolの実装は、「サーバーはまだデータを送信していません」と「ユーザーが操作を取り消したい」と区別できません。 高速接続では動作しないため、実際にはこれら2つのケースを区別する必要があります。 – Alex

+0

なぜTProtocolを気にしますか? RPCコールの後には、TimeoutExceptionスローが発生し、次の処理を決定できます。 – secmask

+0

通信コードのユーザーは、サーバーの応答がまだ到着していない*正当な*ケースでこの例外を取得するためです。タイムアウトが長すぎると、キャンセルの応答がクライアントにとって遅すぎることになります。 私たちは低帯域幅で待ち時間の長い環境で動作しているため、ほとんど常に発生するため、短いタイムアウトを余裕がありません。ただし、引き続きキャンセルしたいと考えています。 – Alex

5

Windowsで実行していると仮定します(ご質問のタグに従って):WSACancelBlockingCallでブロックソケット操作をキャンセルすることができます(この操作は推奨されていませんが、動作するはずです)。ソケットはWSAETIMEDOUTの代わりにエラーコードWSAEINTR (Interrupted function call)を返します。

スリフトでは、TSocket::getSocketFD()またはTPipe::getPipeHandle()を使用して、現在の操作をキャンセルするための対応ハンドルを取得できます。

+0

残念ながら、WSACancelBlockingCallはWinsock2から削除されました。そしてThriftはWinsock2(http://msdn.microsoft.com/en-us/library/windows/desktop/ms741547%28v=vs.85%29.aspx)を使用しています。しかしそれはいい考えです。 – Alex

+0

この関数を使用することはできますが、Winsock2にはまだ存在します(ただし、DLLによってエクスポートされません)。このようなハッキングを使用したくない場合は、別のスレッドからソケットを閉じることもできます。ブロック操作では、エラーWSA_OPERATION_ABORTEDが発生します(Winsock2操作では動作しますが、Winsock1操作では機能しません)。 –

関連する問題