、開封通知はResourceError
にEAGAIN
、EIO
、およびEBADF
をマッピングし、あなたがwaitFor
機能を呼び出したり、ポートを再度開くまでまで、さらに読み取り通知の処理を停止します。これにより、waitFor
を開くまで、QSerialPort
は読み込みに役に立たなくなります。おそらく同じエラーにEIO
とEBADF
をマップするのは理にかなっています。しかし、EAGAIN
は良性なので、そのように扱うにはQtバグのように見えます。
それが問題だ場合、あなたはエラーをクリアしてwaitForReadyRead(0)
またはwaitForBytesWritten(0)
を再呼び出しし、エラーが再び表示された場合に見ることができる表示するには:
bool retryWaitForBytesWritten(int n, int retries = 10) {
if (!dev.bytesToWrite()) return false;
while (retries-- && !dev.waitForBytesWritten(n)) {
if (dev.error() != QSerialPort::ResourceError)
return false;
dev.clearError(); // retry if it was a resource error
}
return true;
}
ので、あなたは主にwaitForBytesWritten
を使用しないでください。
おそらくあなたが思っていることはしません。保証することは、write
システムコールを使用してオペレーティングシステムにデータを供給することによってQSerialPort
の内部書き込みバッファが空になったことだけです。これは、データが物理的に送信されたことを意味するものではありません。
潜在的にブロックされます。ブロックすることは保証されていません。
通常、書き込みが完了したときの通知は必要ありません。ハーフデュプレックス(本質的に)のコマンド応答プロトコルを使用している場合は、送信が終了した時点ではなく、応答が到着したかタイムアウトになったかは気にしません。
ポーリングコマンドを送信し、デバイスが消費するよりも速く生成したくないストリーミングプロトコルを使用している場合は、コマンドを発行してデータ構造内で「発行済み」とマークする必要があります。 bytesToWrite
は最高透かしを超えています。 bytesWritten
シグナルによって、送信バッファが低い透かしになっていることが通知されるまで、新しいコマンドの追加を中断します。 readyRead
スロットは、発行されたコマンドへの応答と一致し、それらを適切に示します。
あなたのコードには、の呼び出しが含まれることが理想的です。私たちの周りの世界は非同期です。あなたは物事を待たずに、に反応します。何かが起きるまでイベントループを止めないでください。それは逆です。あなたが待っていることの前に他のことが起きるかもしれません。あなたはそれまで無視しています。 I/Oを別のスレッドにプッシュしても、ブロックするだけでスレッド全体を無駄にしてしまいます。制御の流れをリダイレクトするイベントを処理することは、順次疑似同期コードでは困難です。すべてが(必要な!)エラーチェックで詰まってしまいます。多くの場合、人々は例外を使用することに頼っています。これは問題ありませんが、大規模なコードベースでは正しく実行するのが難しく、コールスタックにないコードにコントロールをリダイレクトすることを望む場合もあります。着信データやエラーなどの非同期イベントに直面したときに、階層的な状態マシンとして明示的に表現するときに、コードの正確性を判断する方がずっと簡単です。
非同期的に発生するイベントに基づいてシステムが進行するようにシステムを設計します。 UIのいくつかの側面が送信されるデータの状態を示す必要がある場合は、単にそれを次のようにしてください:待機しないで、スレッドをブロックしないでください。
This answerは、ステートマシンフレームワークを使用してQIODevice
に基づくデバイスの非同期I/Oを実装する方法を示しています。状態を設定したら、UIの動作に関連付けるのは比較的簡単です。これらの回答を参照してください。one、two、three、four、five、six、seven、eight
また、私は間違っていて、私はもう一つの答えを修正しました。 QSerialPort
はイベントループを再入力せず、ネットワークモジュールのソケットも再投入しません。
「ResourceError」が何らかのコードを見ることなくなぜ起こるのかを知るのは難しいです。 –
@KubaOber非常に複雑なアプリケーションであり、プロプライエタリな製品の一部であるため、このケースでどれくらいのコードを提供できるかはわかりません。私がいくつかの小さな例に絞り込んだとしても、どの部分が関連しているか分からず、通信層、シリアル通信チャネルの反対側のプロセスなどが最小限の再現可能なケースを作成できませんすべての所有権。 –
...しかし、正確には、ハードウェアのシリアルポートで 'ResourceError'を引き起こすことさえも助けになるでしょう。 –