2016-07-23 3 views
5

Thread.Sleep()メソッドを使用するのが良いか悪いのかについて多くの話があります。私が理解しているところでは、主にデバッグの目的で使用されます。Thread.Sleep()をスレッドを一時停止するのに使用するとパフォーマンスが悪くなるでしょうか?

今私は疑問に思っています。スレッドを一時停止/再開できるように常にループしているというのは、私の特定の目的に使用するのが悪いですか?これは、I/O操作を実行するスレッドを一時停止し、簡単な方法で再開できるためです。

I/O操作は、基本的に、すべてのデータが書き込まれるまで、ファイルに4096バイトのブロックを書き込むだけです。ファイルが大きく、時間がかかることがあるので、私は操作を一時停止できるようにしたい(多くのシステムリソースを食べ始める場合に備えて)。

私のコード、VB.NET版:

'Class level. 
Private BytesWritten As Long = 0 
Private Pause As Boolean = False 

'Method (thread) level. 
While BytesWritten < [target file size] 
    ...write 4096 byte buffer to file... 

    While Pause = True 
     Thread.Sleep(250) 
    End While 

    ...do some more stuff... 
End While 

C#の同等:

//Class level. 
long bytesWritten = 0; 
bool pause = false; 

//Method (thread) level. 
while(bytesWritten < [target file size]) { 
    ...write 4096 byte buffer to file... 

    while(pause == true) { 
     Thread.Sleep(250); 
    } 

    ...do some more stuff... 
} 

私はResetEventsについて聞いていると私は、彼らが何をすべきかについて少し知っているが、私は本当に決してありません彼らに多く見られました。

+2

私はマニュアルリセットイベントを使用します。各チャンクの後、イベントを待ちます。スレッドを一時停止するには、イベントをリセットします。スレッドを再開するには、イベントを設定します。 –

+2

* a * long *操作を一時停止したいと思う理由はわかりません。確かにそれはちょうどそれが長くかかるようになります。ファイルを非同期で書きたい場合は、非同期ファイルIOを使用して結果を待つのはなぜですか? –

+1

@EricLippert:これは、操作が多くのシステムリソースを消費する可能性があるため、アプリケーションのユーザーが一時停止したい場合に使用します。 –

答えて

3

私が思うに、これはそれが

'Method (thread) level. 
    While BytesWritten < [target file size] 
     '...write 4096 byte buffer to file... 

     NotPaused.WaitOne(-1) 

     '...do some more stuff... 
    End While 

を使用される方法であるため、説明に基づいて、私はこの

'Class level. 
Private BytesWritten As Long = 0 
Private NotPaused As New Threading.ManualResetEvent(True) 

行いたい変数名の変更がフィットですこのループを一時停止する

NotPaused.Reset() 

と続ける

NotPaused.Set() 
+1

ありがとうございます。この解決法は、 'ManualResetEvent'が_x_量の呼び出しのために開かれていると思われるセマフォとは別に、" open "または" closed "なので、より良く適合します。今度は、 'ManualResetEvents'がどのように機能するか教えてくれました! –

1

もっとエレガントな方法は、スリープしている最初のスレッドでThread.Interruptを呼び出す別のスレッドが目を覚ますまで、スレッドを無期限にスリープさせることです。これの良い例は、コード例Pausing and Resuming Threadsです。

+1

スレッドを中断することは、デッドロックにつながる可能性がある悪い考えです。 – Groo

+0

ありがとうございました。しかし、私はGrooのように、 'Thread.Interrupt()'が問題を引き起こすかもしれないことに気付いていました。 –

+0

@Grooを訂正していただきありがとうございます。質問に答える際には、ベストプラクティス(気をつけてください)も考えてください。 – hankide

1

あなたがここで達成しようとしていることを誤解しているかもしれませんが、私の見ているところでは、IOタスクが完了するまでスレッドをブロックしようとしているようです。 Thread.Sleep()を行うのではなく、セマフォがここで最善の策になります。

ほとんどのオペレーティングシステムでは、別のスレッドがスリープ解除するまでスレッドを永続的にスリープさせるブロッキングセマフォが提供されています。あなたはおそらく、自分でそのチェックを絶えず行うのではなく、それらを利用する方が良いでしょう。

Thread.Sleep()とブロッキングセマフォの両方がスレッドをスリープ状態にしますが、後者はリソースが解放される(セマフォが署名されている)まで永続的にスリープします。前者はスレッドが常に目を覚まし、確認してスリープ状態に戻ることを要求します。後者はこれらの実行サイクルを節約します。

+0

不明な点をおかけして申し訳ありません。 I/O操作が終了するまでブロックしないで、I/O操作を一時停止しようとしています。私は基本的に、すべてのデータが書き込まれるまで、データのバッファをファイルに書き出します。これは、その作業を一時停止できるようにするには時間がかかることがあるからです。 –

+0

私もこの説明で私の質問を更新しました。 –

+0

偉大な答え!簡潔でわかりやすい説明! –

2

.NETでは、MTAスレッドのテストやデバッグ中に長時間の操作をシミュレートしようとするだけでなく、Thread.Sleepを使用する理由もありません。

おそらく別のオプションはTPLを使用することです。ブロックしたくないので、Task.Delayを使用することができます。ご存じのとおり、タスクは非同期操作を表します。

関連する問題