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

时间:2010-08-11 15:53:24

标签: c# multithreading sleep

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

7 个答案:

答案 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
}