2009-08-25 16 views
2

System.IO.Stream(または任意のラッパーまたはリーダー)を2番目のスレッドから安全に閉じることはできますか?別のスレッドからstream.Closeを呼び出すことはできますか?

私はnew System.IO.StreamReader(inputStream, Encoding.ASCII);のネットワークからの読書をしており、それを閉じることによって別のスレッドからそれをシャットダウンすることを検討しています。

これは良い考えではない場合、読み込み呼び出しのスレッドブロックを強制的に戻す別の方法は何ですか?

答えて

2

盲目的に別のスレッドからCloseメソッドを呼び出すことは安全ではありません。 Streamクラスはスレッドセーフとしてリストされておらず、元のスレッドがを使用している間に別のスレッドからCloseを呼び出すと、未定義の動作が発生します。

1

はい、inputStreamがソケットから読み取っている場合は、ソケット接続を閉じる別のスレッドで処理できます。ブロックされたRead呼び出しは例外をスローすることに注意してください。

1

このような状況で整然とクリーンアップする一般的な方法は、次のとおりです。

  1. は、ブロッキング読み取りがいくつかのデータを取得するようにソケットにいくつかのデータを書き込み完了(例えばIsDone = true
  2. を示す値を設定し
  3. ソケットから読み取っているスレッドで、読み取ったデータを処理する前にIsDoneがtrueであるかどうかを確認します。 IsDoneがtrueの場合は、データを無視してストリームを閉じます。

これは、Jaredが参照している問題を避けるべきです。

+0

まれにしかソケット接続の両端を制御できない場合は、必ずステップ2を実行してください。 –

+0

@マーク:まあ、実際、これはあなたが聞いているのと同じ側からストリームに書き込むことができると仮定しています...私はその1つで昼食に出るかもしれません... –

0

はい、別のスレッドでストリームを閉じても問題ありません。他のスレッドがそのストリームを使用している場合、例外が発生します。正しいことは、読み取りを行っているスレッドがシャットダウンするかどうかを確認できるイベントまたは待機ハンドルのいずれかを持つことです。擬似コードは次のようになります。 スレッド1 読み取り操作を保留し、読み取るデータがあるかどうかを確認します。
データの場合は、データを読み込みます。そうでない場合は、 待機ハンドルを確認してください。それが設定されていればそれを閉じて終了してください。それ以外の場合はもう一度お読みください ループ

スレッド2 切断するためにネットワークを起動する必要がある場合は、

ブロック操作中は、例外が発生することに注意してください。私はブロッキングソケットを使用しないことをお勧めします。理由はありません。私たちは実際には、System.Netのフードの下で(ほとんどの)非同期操作を行い、シンクコードパスは非同期コードパスをトリガーし、完了するまでブロックします。

+0

ジェフ:それは見るのが面白いでしょうこれのコード例leeeroyはStreamReaderを使用しています。非同期メソッドはありません。つまり、ネットワークストリームから直接読み取ってから、読み取った値をテキストエンコーダに「ポンピング」する必要がありますか? – JMarsch

+0

StreamReader.Readはブロックされないため、非同期メソッドは必要ありません(それ以上データが存在しない場合は-1を返します)。あなたがしたいことは、次のようなものです: while(someCondition){ if(handle.WaitOne(1)){//ストリームを破棄する時刻 stream.Close(); stream.Dispose(); myStreamDisposalCompleteHandle.Set() }他{//ストリームは依然として データ= stream.Readを(使用する結構です)//これは他のスレッドで }ノンブロッキングれる: IF(appShouldCloseStreams){foreachの (HandlesThatStreamsHaveのstreamShouldCloseHandleハンドル) handle.Set(); WaitHandle.WaitAll(arayOfAllStreamDisposeCompleteHandles); App.Exit(); –

+0

上記のフォーマットについてお詫び申し上げます。そのコードでは、ストリームを処理する各スレッドに2つのハンドルがあります.1つは定期的にチェックして閉じるべきかどうかを確認し、もう1つはストリームを閉じたことを知らせるために使用できるハンドルです。メインスレッドは、すべてのストリームスレッドが持つすべてのハンドルへの参照を持ちます。終了することを知らせる準備ができたら、それは他のすべてのスレッドに信号を送り、終了したことを知らせるのを待ちます。ハンドルにManualResetEventクラスまたはAutoResetEventクラスを使用すると、WaitHandleは基本クラスですが、Setメソッドはありません。 –

関連する問題