当用于暂停线程时,循环 Thread.Sleep() 会对性能产生不利影响吗?

Would looping Thread.Sleep() be bad for performance when used to pause a thread?

关于使用 Thread.Sleep() 方法是好是坏,有(或已经有)很多讨论。据我了解主要是用来调试的。

现在我想知道:我的特定用途,即不断循环它以能够 pause/resume 线程是否不好?我这样做是因为我想暂停执行 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 并且我对它们的作用略知一二,但我从未真正深入研究过它们。

我认为更优雅的方法是让线程无限期地休眠,直到它被另一个线程唤醒,该线程在第一个休眠的线程上调用 Thread.Interrupt。示例代码中有一个很好的示例:Pausing and Resuming Threads.

我可能误解了您在这里要实现的目标,但据我所知,您似乎在尝试阻塞线程直到 IO 任务完成。信号量在这里是最好的选择,而不是 Thread.Sleep()。

大多数操作系统都提供阻塞信号量,使线程永久休眠,直到另一个线程将其唤醒。你最好利用它们而不是不断地自己检查。

Thread.Sleep() 和阻塞信号量都会使线程进入睡眠状态,但后者会一直这样做,直到资源被释放(信号量已被签名)。前者需要线程不断地唤醒、检查、再回到睡眠状态。后者节省了这些执行周期。

在 .NET 中,除了在 MTA 线程上测试和/或调试时尝试模拟冗长的操作外,没有理由使用 Thread.Sleep,因为它会阻塞。

也许另一种选择是使用 TPL. Since you don't want to block you can use Task.Delay。您可能知道,一个 Task 代表一个异步操作。

我想,根据描述,我会这样做

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

变量名的变化是合适的,因为这是它的使用方式

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

        NotPaused.WaitOne(-1)

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

要使循环暂停,请执行此操作

    NotPaused.Reset()

并继续

    NotPaused.Set()