有没有办法在C#中唤醒睡眠线程?那么,让它长时间睡眠并在你想要处理工作时将其唤醒?
答案 0 :(得分:16)
可以使用AutoResetEvent
对象(或其他WaitHandle
实现)进行休眠,直到收到来自另一个线程的信号:
// 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();
答案 1 :(得分:5)
如果你的线程在Sleep
的调用内,那么(通常)没有办法将其唤醒。 (我所知道的唯一例外是Java,它允许在其他线程调用thread.interrupt()
时提前结束睡眠。)
您正在谈论的模式似乎要求一个事件:该线程包含一个循环,在其顶部等待事件触发。如果事件当前未设置,则线程“休眠”,直到某个其他线程触发该事件。此时,睡眠线程唤醒并继续其工作,直到下一次通过循环时它休眠等待另一个事件。
答案 2 :(得分:2)
C#中实际上有一个thread.Interrupt()方法。 虽然接受的答案确实描述了你可能想要的一个好的模式,但我来到这个问题寻找Thread.Interrupt所以我把它放在这里。
答案 3 :(得分:1)
最佳解决方案是使用默认Task
的{{1}}个对象。这个API(在.NET 4.0中引入)使用一个带有工作窃取队列的线程池和所有那些花哨的东西。
如果.NET 4.0不可用,则使用TaskFactory
,它具有内置工作队列(可以进行一些池平衡但不在与4.0线程池相同的范围内)。
如果您确实必须自己做,那么我建议使用ThreadPool
,这是在.NET 4.0中添加的阻塞使用者/生产者队列。
如果你真的必须自己做并且不能使用.NET 4.0,那么你可以使用BlockingCollection<T>
或ManualResetEvent
使用AutoResetEvent
- 受保护的工作队列。
答案 4 :(得分:0)
this线程有帮助吗? C#有good functionality用于线程事件处理。我在Python中完成了大部分工作,但C#似乎有用于线程阻塞的可靠库。
答案 5 :(得分:0)
根据伊利亚的建议:
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
被抛出。
答案 6 :(得分:0)
扩展Wim的答案你也可以指定WaitHandle.WaitOne()
电话的超时时间。因此,您可以使用而不是Thread.Sleep()
。 CancellationToken
struct为您提供一个结构,以便您可以发出如下信号:
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
}