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

Posted

技术标签:

【中文标题】有没有办法唤醒睡眠线程?【英文标题】:Is there a way to wake a sleeping thread? 【发布时间】:2011-03-28 11:30:36 【问题描述】:

有没有办法唤醒 C# 中的休眠线程?那么,让它休眠很长时间,然后在您想要处理工作时唤醒它?

【问题讨论】:

究竟是在什么环境下?我们真的需要更多关于您正在使用的平台和/或线程模型的信息才能有意义地回答这个问题。 这取决于你如何让它进入睡眠状态。 你肯定至少要告诉我们这个问题是关于什么编程语言的。 它是 C# - 我认为它可能与语言有关。 这是一个有用的帖子Safely wake and exit a sleeping C# thread without Thread.Abort()。 【参考方案1】:

一个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();

【讨论】:

【参考方案2】:

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

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

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

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

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

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

如果你真的必须自己做并且不能使用.NET 4.0,那么你可以使用ManualResetEventAutoResetEvent以及@987654327 @-protected 工作队列。

【讨论】:

这没有回答问题“如何唤醒沉睡的踏板?”,我们如何通过Task 获得所需的功能?【参考方案5】:

扩展 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

【讨论】:

【参考方案6】:

this 线程有帮助吗? C# 有 good functionality 用于线程事件处理。我在 Python 中完成了大部分工作,但 C# 似乎有可靠的线程阻塞库。

【讨论】:

【参考方案7】:

根据伊利亚的建议:

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 被抛出。

【讨论】:

以上是关于有没有办法唤醒睡眠线程?的主要内容,如果未能解决你的问题,请参考以下文章

Thread类线程结束会唤醒使用其对象做锁而睡眠的线程

在 Rust 的 sigint 上唤醒一个睡眠线程?

唤醒一个处于睡眠状态的 QThread?

每个条件唤醒多个线程工作一次

多线程模块

线程同步的方法