如何在C#中唤醒睡眠线程?

时间:2010-12-31 04:25:03

标签: c# .net sleep thread-abort

在人们提出建议之前:除了试图找到解决方法之外,我没有将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()显然对睡眠线程没有任何作用。

有没有办法唤醒一个线程,而不等待它的Sleep过期?我知道停止不是“立即”,因此无论如何都可以调用Console.WriteLine;这是等待我的2秒等待。如果等待10天怎么办?由于我无法控制进来的线程,我无法知道,似乎无法阻止这样的事情......

2 个答案:

答案 0 :(得分:2)

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

但要解决运行时的原因问题:

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

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

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

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

我不确定你想用额外的外线来完成什么。这不会更简单:

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

答案 1 :(得分:0)

使用WaitOne +计时器来控制未知来源的线程。

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

有点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使用特性