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

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

【问题讨论】:

  • 究竟是在什么环境下?我们真的需要更多关于您正在使用的平台和/或线程模型的信息才能有意义地回答这个问题。
  • 这取决于你如何让它进入睡眠状态。
  • 你肯定至少要告诉我们这个问题是关于什么编程语言的。
  • 它是 C# - 我认为它可能与语言有关。

标签: c# multithreading sleep


【解决方案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 被抛出。

            【讨论】:

              猜你喜欢
              • 2014-07-29
              • 1970-01-01
              • 2018-12-04
              • 1970-01-01
              • 1970-01-01
              • 2014-05-15
              • 2010-12-16
              • 2011-07-29
              • 1970-01-01
              相关资源
              最近更新 更多