2012-03-10 10 views
0

私はファイル転送アプリケーション(サーバークライアント)を持っています...ファイルを送信中に、私はキャンセルを有効にしたいと思います。
クライアントBackgroundworkerが動作するSendFileメソッドをキャンセルし、サーバーに受信スレッドをキャンセルするコマンドを送信します。
サーバがこのコマンドを受信したときに、メソッドを停止します。メソッドを停止しますが、その行にスタックします。network.Read(data、0、data.Length);Thread.Abort()がNetworkStream.Readにスタックしましたか?

このスレッドを中止してに移動するにはどうすればいいですか? network.Read(..)にくっついていませんか?ありがとうございます。

Thread thTransferFile = null; 

void Start() 
{ 
    thTransferFile = new Thread(unused => ft.Receive(destPath, Convert.ToInt64(fileSize); 
    thTransferFile.Start(); 
} 

void Stop() 
{ 
    thTransferFile.Abort(); 
} 


public void Receive(string destPath, long fileSize) 
    { 
     using (fs = new FileStream(destPath, FileMode.Create, FileAccess.Write)) 
     { 
      try 
      { 
       int count = 0; 
       long sum = 0; 
       data = new byte[packetSize]; 
       while (sum < fileSize) 
       { 
        count = network.Read(data, 0, data.Length); //thread stucks in this line when i abort it 
        fs.Write(data, 0, count); 
        sum += count; 
       } 
      } 
      finally 
      { 
       network.Write(new byte[1], 0, 1); //tell client that the file transfer ends 
       network.Flush(); 
       fs.Dispose(); 
       if (Thread.CurrentThread.ThreadState == ThreadState.AbortRequested) 
       { 
        File.Delete(destPath); 
       } 
      } 
     } 
+0

'Thread.Abort'は*ほとんど常に*間違ったことです。 –

+0

@Damien_The_Unbelieverだからそれが間違っているなら何が正しいことですか? –

+0

それはあなたが感じている勇気にかかっています。もしあなたが.NET 4.5へのジャンプをする準備ができていれば、 'CancellationToken'をとる' ReadAsync'のオーバーロードが一番うまくいくでしょう。さもなければ、@DanielMošmondorが言うように、 'network'オブジェクトを' Close'または 'Dispose'します。 –

答えて

0

私はクライアント側から送信キャンセルとき、私は.. network.DataAvailableをfalseに設定..ソリューション を見つけたので、私は私の中では、サーバー

でメソッドを受信するには、この行を追加しましたループ:

   while (sum < fileSize) 
       { 
        if (network.DataAvailable) 
        { 
         count = network.Read(data, 0, data.Length); 
         fs.Write(data, 0, count); 
         sum += count; 
        } 
       } 

これは決してnetwork.Readでスタックしません。 それは完全に働いた

+1

利用可能なデータを確認することは間違いなく正しい方向に進んでいますが、全体的なソリューションはあまりにもスピンロックを思い起こさせます。コード実行時にデータを使用できない頻度はどのくらいですか? – Tung

+0

@Tung私が望んでいるのは、スレッドのものを中断しているので、私のコードについて説明していない。しかし、私のアプリケーションを構築した方法.. network.DataAvailableは、キャンセルまたはネットワークが閉じるまで常にtrueです。これらの2つの場合のみである。 –

1

代わりのスレッド、Close()networkを中止。あなたが予期しているように例外がスローされます。それは、データを受信するまでNetworkStream.Readがブロックされている

+0

私は()ネットワークを閉じることができません..私はファイルを送信するたびに再接続しないでください..その動作しないだろう。 –

+0

次に、非同期のものを使用する必要があります。 BeginRead()など。私はそれがすべての問題を複雑にしていることは知っていますが、他の方法はわかりません。 –

+0

ダニエルに感謝します。私はそれを解決する方法を考え出しました。私の答えを確認してください。 –

1

汚れたままにしておくことができ、リソースが...あるので、スレッドを殺す

は、ノーノー大きいです。 NetworkStreamのReadTimeoutRead the community commentを使用して、読み取り操作でタイムアウトを設定します。また、スレッドを強制終了するためにAbort()を再考することもできます。 whileループにbooleanフラグを追加し、Stop()が呼び出されたときにそのフラグをfalseに設定します。この停止フラグとReadTimeoutを組み合わせると、プログラムが確実に終了します。

が中止されたスレッドは、catchブロック、 finallyブロック、または拘束実行領域として、コードの保護された領域内にある場合にアボートがブロックされるコールのスレッド。 がAbortを呼び出すスレッドが、中止されたスレッドが必要とするロックを保持している場合は、デッドロック が発生する可能性があります。

+0

ReadTimeoutで設定する時間はどれくらいですか。ネットワークはいつか何らかの理由で遅れていることを知っています。私はパケットを受け取るたびにフラグをチェックするよりも優れていると思っています。プラス私はそのスレッドが「保護された領域」を実行するために必要です] ..FileStreamはどんな場合でも(エラー、取り消し、成功)処分します。 –

+0

@ Mur、私はReadTimeoutが最適ではないことに同意します。あなたはどれくらいの長さであるかは決して特定できませんが、高い値は無限より優れています。代わりにBeginReadの使用を検討しましたか?他のメンバーが指摘しているように、 'Abort()'は一般的にはお勧めできません。スレッドが中断したときにスレッドが何をしているのかは決して特定できません。ここに1つの[ディスカッション](http://stackoverflow.com/questions/3923457/is-cs-using-statement-abort-safe)です。また、tryブロック内でAbort()が実行された場合にのみfinallyブロックが実行されると考えられます。 – Tung

+0

@Tung - 私は、誤った前提でコードを構築しないことを願っています。このメソッドは、bufferパラメーターにデータを読み込み、正常に読み取られたバイト数を返します。読み込み可能なデータがない場合、Readメソッドは0を返します.Read操作は、sizeパラメータで指定されたバイト数まで、利用可能なデータを読み込みます。リモートホストが接続をシャットダウンし、利用可能なすべてのデータを受信した場合、Readメソッドはただちに完了し、ゼロバイトを返します。 (http://msdn.microsoft.com/en-us/library/system.net.sockets.networkstream.read.aspxから取得) –

関連する問題