中断睡眠线程

Jef*_*ddy 12 c# multithreading

有没有办法让睡眠线程中断?如果我有类似的代码.

while(true){
    if(DateTime.Now.Subtract(_lastExecuteTime).TotalHours > 1){
        DoWork();
        _lastExecuteTime = DateTime.Now();
        continue; 
    }
    Thread.Sleep(10000) //Sleep 10 seconds
    if(somethingIndicatingQuit){
        break;
    }

}
Run Code Online (Sandbox Code Playgroud)

我想每小时执行一次DoWork().所以,我想睡10秒钟.每10分钟左右检查一次.但是,如果将我的睡眠设置为10分钟,并且我想要终止此后台任务,我必须等待睡眠恢复.

我的实际代码是使用Threading.ManualResetEvent来关闭后台工作,但我的问题是使用ThreadSleep代码.如有必要,我可以发布更多代码.

好的,我将在这里添加一些更完整的代码,因为我认为它将回答一些问题.

private readonly ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private readonly ManualResetEvent _pauseEvent = new ManualResetEvent(true);
private Thread _backGroundWorkerThread;

//This starts our work
public void Start() {
    _backGroundWorkerThread = new Thread(ExecuteWorker) {IsBackground = true, Name = WorkerName + "_Thread"};
    _shutdownEvent.Reset();
    _backGroundWorkerThread.Start();
}
internal void Stop() {
    //Signal the shutdown event
    _shutdownEvent.Set();

    //Make sure to resume any paused threads
    _pauseEvent.Set();

    //Wait for the thread to exit
    _backGroundWorkerThread.Join();

}

private void ExecuteWorker() {
    while (true) {
        _pauseEvent.WaitOne(Timeout.Infinite);

        //This kills our process
        if (_shutdownEvent.WaitOne(0)) {
           break;
        }

        if (!_worker.IsReadyToExecute) {
            //sleep 5 seconds before checking again. If we go any longer we keep our service from shutting down when it needs to.
            Thread.Sleep(5000);
            continue;
        }
        DoWork();

    }
}
Run Code Online (Sandbox Code Playgroud)

我的问题在这里,

_backGroundWorkerThread.Join();
Run Code Online (Sandbox Code Playgroud)

这等待在我的后台线程中运行的ExecuteWorker()中的Thread.Sleep.

Jon*_*eet 35

Thread.Sleep您可以使用Monitor.Wait超时 - 而不是使用- 然后您可以使用Monitor.Pulse其他线程将其唤醒.

不要忘记在调用之前你需要锁定显示器WaitPulse:

// In the background thread
lock (monitor)
{
    // If we've already been told to quit, we don't want to sleep!
    if (somethingIndicatingQuit)
    {
        break;
    }
    Monitor.Wait(monitor, TimeSpan.FromSeconds(10));
    if (somethingIndicatingQuit)
    {
        break;
    }
}

// To wake it up...
lock (monitor)
{
    somethingIndicatingQuit = true;
    Monitor.Pulse(monitor);
}
Run Code Online (Sandbox Code Playgroud)

  • 如果Jon Skeet给你一个答案并且它*不起作用,那你就错误地实现了他的答案:) (22认同)
  • 这是一个很好的答案 - 解决了我的问题,这是我发现的最好的Monitor示例.一个小小的请求 - 你能更新你的答案来澄清`monitor`变量是什么吗?对某些人来说可能是显而易见的,但我不得不环顾四周.谢谢! (2认同)
  • 确实很好的答案 - 下面的链接也非常有帮助:http://www.albahari.com/threading/part4.aspx#_Signaling_with_Wait_and_Pulse (2认同)

Bri*_*eon 15

而不是Thread.Sleep使用ManualResetEvent.WaitOne.

while (true) {
    if(DateTime.Now.Subtract(_lastExecuteTime).TotalHours > 1) {
        DoWork();
        _lastExecuteTime = DateTime.Now();
        continue; 
    }
    if (terminate.WaitOne(10000)) {
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

哪里terminate是一个ManualResetEvent1,你可以Set请求循环的终止.

更新:

我刚刚注意到你说你已经在使用ManualResetEvent终止后台工作(我假设它已经存在DoWork).你有什么理由不能使用相同的MRE吗?如果那是不可能的,那么使用不同的问题当然不应该是一个问题.

更新2:

是啊,所以不是Thread.Sleep(5000)ExecuteWorker_shutdownEvent.WaitOne(5000)代替.它看起来如下.

private void ExecuteWorker() {
    while (true) {
        _pauseEvent.WaitOne(Timeout.Infinite);

        //This kills our process
        if (_shutdownEvent.WaitOne(0)) {
           break;
        }

        if (!_worker.IsReadyToExecute) {
            //sleep 5 seconds before checking again. If we go any longer we keep our service from shutting down when it needs to.
            _shutdownEvent.WaitOne(5000);
            continue;
        }
        DoWork();
    }
}
Run Code Online (Sandbox Code Playgroud)

1ManualResetEventSlim .NET 4.0中还有一个类.