【问题标题】:How can I wake a sleeping thread in C#?如何唤醒 C# 中的睡眠线程?
【发布时间】:2011-06-01 20:52:04
【问题描述】:

在人们建议之前:我没有将 Thread.sleep 用于任何事情,只是想找到一种解决方法。我正在尝试处理其他人的未来代码,这些代码可能不是 .Sleep() 免费的。我非常清楚同步事物的可怕之处。

我在我的代码块中接受一个线程。我希望能够为这个线程的生命周期设置一个限制。我通常这样做的方法是这样的:

Thread outer = new Thread(() =>
{
    externalThread.Start();
    externalThread.Join();
});
outer.Start();
outer.Join(lifetime);
if (outer.ThreadState != ThreadState.Stopped)
{
    outer.Abort();
}
inner.Join();

从那以后,我发现我显然无法在睡眠结束之前唤醒睡眠线程。更糟糕的是,如果我给它 10 毫秒的生命周期,它仍然会写入控制台:

new Thread(() => { Thread.Sleep(2000); Console.WriteLine("second"); })

虽然我意识到 .Abort() 不是线程执行的硬限制。似乎 2 秒就足够了一个警告,但我想不是......

我已尝试检查 WaitSleepJoin 状态和 .Interrupt();它使线程崩溃,或引发异常(抱歉,不确定是哪个。Windows 告诉我,如果没有调试器正在运行,它就会崩溃,如果它正在运行,它就像没有调用中断一样运行),并且仍然在 2 秒后写入控制台. .Resume() 显然对睡眠线程没有任何作用。

有没有办法唤醒一个线程,而不用等待它的睡眠过期?我知道停止不是“立即的”,因此无论如何都可以调用 Console.WriteLine;这是困扰我的 2 秒等待。如果等了10天呢?由于无法控制进来的线程,我无从知晓,而且似乎也没有办法防止这样的事情……

【问题讨论】:

  • 你将如何引用其他人的线程?
  • void myFunc(Thread externalThread){ // 大约。上面的代码}
  • 如果等待 10 天,请告诉您的主管,以便可以解雇这样做的开发人员。不要试图掩盖不称职的开发人员的所有可能的白痴。
  • 我真的看不出你想从问题中实现什么。它是某种任务管理器吗?请提供更多详细信息。
  • @chibacity:这是运行代码块的长任务的一半,因此我可以触发 ajax 事件并轮询它们的进度。这是总体管理器代码。

标签: c# .net sleep thread-abort


【解决方案1】:

不,没有办法从睡眠中唤醒线程。您只能通过调用 Abort 或 Interrupt(两者都抛出 ThreadAbortException)来中止线程。

但是为了解决你为什么在运行时的问题:

new Thread(() => { Thread.Sleep(2000); Console.WriteLine("second"); })

仍然会打印 10 毫秒超时,这是因为您用于控制线程生命周期的代码没有执行您想要执行的操作。

所以你有 externalThread 和 external。您启动外部(它启动一个新线程,我们称之为线程 1)并从外部调用开始于外部线程(它启动一个新线程,我们称之为线程 2)。所以你刚刚开始了两个新线程。

当您调用 outer.About() 时,只会中止线程 1。通过调用 externalThread.Start() 启动的线程,线程 2 会继续执行直到完成,因为没有任何内容会中止它。

我不确定你想用额外的外螺纹来完成什么。这不是更简单吗:

externalThread.Start();
externalThread.Join(lifetime);
if (externalThread.ThreadState != ThreadState.Stopped)
{
    externalThread.Abort();
}

【讨论】:

  • 如果我没有产生一堆线程,它会的;我需要一种程序化的方式来阻止它们。由此,以及一些实验,我有一个“duh”的时刻:Abort 没有被传播。出于某种原因,我一直认为线程在某种程度上取决于它们的开始位置,但现在我明白为什么不能这样了。感谢您的回复!
【解决方案2】:

使用 WaitOne + timer 来控制未知来源的线程。

或者如果您可以控制线程的工作代码:

有点 hacky 的方式,在不喜欢计时器/用于唤醒线程的其他线程时实现更多的“响应式睡眠”

用它代替普通的 Thread.Sleep

    private void WaitFor(int milis)
    {
        const int interval = 500;

        if (milis <= interval)
        {
            throw new ArgumentException();
        }

        var sections = milis / interval;
        for (var s = 0; s < sections && (!ShouldQuit); ++s)
        {
            Thread.Sleep(interval);
        }
    }

注意 ShouldQuit 标志,它是一个可从两个线程访问的类字段

当然,这比基于事件/计时器的等待具有更糟糕的 CPU 使用特性

【讨论】:

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