2013-08-29 8 views
9

Ich benutze Apache-Sparsamkeit in C++ unter Windows und ich möchte um Ihre Hilfe mit dem Abbruch eines blockierenden Lesevorgangs bitten, der gerade ausgeführt wird. Die Leseoperation (zum Beispiel - TProtocol :: readByte) ist blockiert, bis die Daten empfangen werden. Wenn ich den Transport von einem anderen Thread schließe, erhalte ich eine fehlgeschlagene Assertion über einen Nullzeiger.Einen blockierenden Lesevorgang in Thrift abbrechen

Gibt es eine andere Möglichkeit, eine blockierte Leseoperation abzubrechen?

Antwort

3

Wenn Sie den Blockiermodus verwenden, ist die einzige Option zum Abbrechen der Leseoperation ein Timeout auf der TSocket, bevor sie gelesen wird.

+0

In diesem Fall kann jede Implementierung von TProtocol nicht unterscheiden zwischen "der Server hat noch keine Daten gesendet" und "der Benutzer möchte den Vorgang abbrechen". Da wir nicht über eine schnelle Verbindung arbeiten, müssen wir wirklich zwischen diesen beiden Fällen unterscheiden. – Alex

+0

Warum interessieren Sie sich für TProtocol? Nach dem RPC-Aufruf gibt es einen TimeoutException-Throw für beide Fälle, und Sie können entscheiden, was als Nächstes gilt. – secmask

+0

Da der Benutzer unseres Kommunikationscodes diese Ausnahme im * legitimen * Fall erhält, in dem die Antwort des Servers noch nicht angekommen ist. Wenn meine Zeitüberschreitung zu lang ist, ist die Antwort der Stornierung für unseren Kunden zu langsam. Da wir in einer Umgebung mit geringer Bandbreite und hoher Latenz arbeiten, können wir uns keine kurzen Timeouts leisten, da sie fast immer vorkommen. Wir wollen jedoch immer noch absagen. – Alex

5

Angenommen, Sie laufen unter Windows (entsprechend den Tags in Ihrer Frage): Sie können einen blockierenden Socket-Vorgang mit WSACancelBlockingCall abbrechen (obwohl dieser Vorgang veraltet ist, sollte es noch funktionieren). Ihr Socket wird dann den Fehlercode WSAEINTR (Interrupted function call) anstelle von WSAETIMEDOUT zurückgeben.

In Thrift können Sie TSocket::getSocketFD() oder TPipe::getPipeHandle() verwenden, um das entsprechende Handle für das Abbrechen des aktuellen Vorgangs zu erhalten.

+0

Leider wurde WSACancelBlockingCall aus Winsock2 entfernt. Und Thrift verwendet Winsock2 (http://msdn.microsoft.com/en-us/library/windows/desktop/ms741547%28v=vs.85%29.aspx). Aber es ist eine nette Idee. – Alex

+0

Sie können die Funktion verwenden, sie ist immer noch in Winsock2 vorhanden (obwohl sie nicht von der DLL exportiert wird). Wenn Sie einen solchen Hack nicht verwenden möchten, können Sie den Socket auch von einem anderen Thread schließen. Die blockierende Operation erhält den Fehler WSA_OPERATION_ABORTED (funktioniert für Winsock2-Operationen, aber nicht für Winsock1-Operationen). –