有没有办法唤醒睡眠线程?

有没有办法在C#中唤醒一个睡眠线程? 那么,让它睡了很长时间并在你想要处理工作时将其唤醒?

可以使用AutoResetEvent对象(或另一个WaitHandle实现)进行hibernate,直到收到来自另一个线程的信号:

 // launch a calculation thread var waitHandle = new AutoResetEvent(false); int result; var calculationThread = new Thread( delegate { // this code will run on the calculation thread result = FactorSomeLargeNumber(); waitHandle.Set(); }); calculationThread.Start(); // now that the other thread is launched, we can do something else. DoOtherStuff(); // we've run out of other stuff to do, so sleep until calculation thread finishes waitHandle.WaitOne(); 

如果你的线程在Sleep的调用中,那么(通常)没有一种方法可以唤醒它。 (我唯一知道的例外是Java,如果其他一些线程调用thread.interrupt() ,它允许睡眠提前结束。)

你正在谈论的模式似乎要求一个事件:线程包含一个循环,在它的顶部等待一个事件被触发。 如果事件当前未设置,则线程“hibernate”,直到某个其他线程触发该事件。 此时,睡眠线程唤醒并继续其工作,直到下一次通过循环时它hibernate等待另一个事件。

C#中实际上有一个thread.Interrupt()方法。 虽然接受的答案确实描述了一个你可能想要的好模式,但我来到这个问题寻找Thread.Interrupt,所以我把它放在这里。

最好的解决方案是使用具有默认TaskFactory Task对象。 这个API(在.NET 4.0中引入)使用一个带有工作窃取队列的线程池和所有那些花哨的东西。

如果.NET 4.0不可用,那么使用ThreadPool ,它具有内置工作队列(它可以进行一些池平衡但不在与4.0线程池相同的范围内)。

如果你真的必须自己做,那么我推荐一个BlockingCollection ,这是一个在.NET 4.0中添加的阻塞消费者/生产者队列。

如果您真的必须自己动手并且不能使用.NET 4.0,那么您可以使用ManualResetEventAutoResetEvent以及受保护的lock工作队列。

这个post有帮助吗? C#具有良好的线程事件处理function 。 我在Python中完成了大部分工作,但C#似乎有用于线程阻塞的可靠库。

根据伊利亚的建议:

 t1 = new Thread(() => { while (keepRunning) { try { DoWork(); Thread.Sleep(all_night_long); } catch (ThreadInterruptedException) { } } }); t1.Start(); 

和…

 public void WakeUp() { t1.Interrupt(); } public void StopRunningImmediately() { keepRunning = false; WakeUp(); //immediately } 

此解决方案很粗糙,因为可能还有其他原因导致抛出ThreadInterruptedException

扩展Wim的答案,您还可以为WaitHandle.WaitOne()调用指定超时。 所以你可以使用而不是Thread.Sleep()CancellationToken结构为您提供一个,以便您可以发出如下信号:

 string SleepAndWakeUp(string value,CancellationToken ct) { ct.WaitHandle.WaitOne(60000); return value; } void Parent() { CancellationTokenSource cts = new CancellationTokenSource(); Task.Run(() => SleepAndWakeUp("Hello World!", cts.Token), cts.Token); //Do some other work here cts.Cancel(); //Wake up the asynch task }