4

USB デバイスとやり取りするために C# で作成したユーティリティがあります。汎用の HID ドライバーを使用し、デバイスへのハンドルをFileStreamオブジェクトにラップします。BeginReadメソッドとメソッドを使用してデータの読み取り/書き込みを行いBeginWriteます。これは、非同期 IO が必要だからではなく、デバイスが (意図的かどうかに関係なく) 通信不能状態になった場合にタイムアウトできるようにするためです。すべての読み取り/書き込みは、独自の専用 IO スレッドで行われます。

スレッドのデッドロックが疑われるケースをいくつか見たので、私は物事を適切に行っていないのではないかと心配しています。これは、関連するReadメソッドの簡略化されたバージョンです (これはうまく機能しているようです)。

if (_readResult == null)
{
  _readResult = _deviceStream.BeginRead(_readBuffer, 0, _readBuffer.Length, null, null);
}

if (_readResult.AsyncWaitHandle.WaitOne(IOTimeout, true))
{
  int bytesRead = _deviceStream.EndRead(_readResult);
  _readResult.AsyncWaitHandle.Close();
  _readResult= null;
  // … Copy bytes to another buffer
}
else
{
  // … Timeout, so retry again in a bit
}

私の主な質問は、IO スレッドを終了する必要があり、デバイスが通信しなくなった場合に、未完了BeginReadまたは呼び出しを適切に停止する方法です。そこに座って永遠にブロックするので、BeginWrite私はただ電話することはできません。読み取り/書き込み操作が保留中EndReadに呼び出しても安全ですか?Filestream.Close

また、保留中の読み取り操作と書き込み操作を同時に実行しても安全ですか? たとえば、読み取りメソッドがタイムアウトした場合でも、先に進んで何かを書き込もうとすることはできますか?

現在のデッドロックの問題を再現するのは難しいですが、本当に奇妙なのは、読み取りメソッドで IO スレッドが「スタック」したときに開始するように見えることです。私のコードが思った通りに動作しない限り、それがどのように起こるかはわかりません。

4

1 に答える 1

6

組み込みのキャンセルはありません。ストリームを閉じることをお勧めします。EndRead を呼び出すときに必ず例外をキャッチしてください...

.NET 4.5 を使用する場合は、FileStream.ReadAsyncキャンセルをサポートする新しいものがあります: http://msdn.microsoft.com/en-us/library/hh158566(v=vs.110 )

于 2012-08-02T21:09:42.887 に答える