在用于暂停线程时,循环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,我知道他们做了什么,但我从来没有真正了解过它们。

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

 '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() 

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

也许另一种选择是使用TPL 。 由于您不想阻止,您可以使用Task.Delay 。 您可能知道,Task表示异步操作。

我认为更优雅的方法是让线程无限期地睡眠,直到被第一个正在hibernate的线程上调用Thread.Interrupt的另一个线程唤醒它。 在示例代码中有一个很好的例子: 暂停和恢复线程 。

我可能误解了你在这里想要实现的目标,但从我看到的情况来看,似乎你试图在IO任务完成之前阻塞一个线程。 信号量将是这里最好的选择,而不是做Thread.Sleep()。

大多数操作系统都提供阻塞信号量,使线程永久hibernate,直到另一个线程唤醒它。 你可能最好不要使用它们而不是经常自己检查。

Thread.Sleep()和阻塞信号量都使线程进入hibernate状态,但后者在资源被释放(信号量已被签名)之前一直执行该操作。 前者需要线程不断唤醒,检查并重新入睡。 后者保存了这些执行周期。