有没有办法唤醒睡眠线程?
有没有办法在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,那么您可以使用ManualResetEvent
或AutoResetEvent
以及受保护的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 }