如何终止/退出/中止旧的线程工作程序并重新启动程序

本文关键字:线程 工作程序 程序 重新启动 何终止 终止 退出 | 更新日期: 2023-09-27 18:19:31

我有这些控制按钮(Windows.Forms):

Start/Restart|Pause|Continue

一旦按下Start,就会创建threadPool[workerThreadsCount]ManualResetEvent mre被设置为mre.Set(),线程开始执行它们的工作。在一些伪代码中:

threadStartingPoint() {
int index = 0;
while(index !== someMaxCondition)
      ... // grab some data to work on
      lock(_lock) {  // lock index, so one access at a time
        index += index;
      }
      ... // do some stuff
      _mre.WaitOne(); // Pause if button Pause is pressed.
    }
}

工作线程在一个循环中工作,就像上面的例子一样。现在,如果我按下pause,一切都会停在_mre.Wait();的位置。使用continue,我可以使用mre.Set()打开闸门,一切都很好。现在的问题是,当我Pause时,我希望用户在ContinueRestart之间进行选择。Restart的问题在于,我不知道如何告诉我的线程退出该while loop。因为如果我只是设置mre.Set()并创建新线程,那么在一段时间内,旧线程仍将使用旧数据循环。

有什么建议吗?

如何终止/退出/中止旧的线程工作程序并重新启动程序

传入CancellationToken并检查每个循环。

private volatile CancellationTokenSource _tokenSource = new CancellationTokenSource();
threadStartingPoint() {
int index = 0;
var token = _tokenSource.Token;
while(index !== someMaxCondition && !token.IsCancellationRequested)
      ... // grab some data to work on
      lock(_lock) {  // lock index, so one access at a time
        index += index;
      }
      ... // do some stuff
      _mre.WaitOne(); // Pause if button Pause is pressed.
    }
}

当用户单击Cancel按钮时,让它向派生令牌的CancellationTokenSource发送Cancel。然后,新的工作人员可以只使用一个不受先前取消影响的新令牌源。

private void ButtonCancelClick(object sender, EventArgs e)
{
    //Get a local copy of the source and replace the global copy
    var tokenSource = _tokenSource;
    _tokenSource = new CancellationTokenSource();
    //Cancel all loops that used the old token source
    tokenSource.Cancel();
    mre.Set();
}

答案是考虑实现CancellationTokenSource。

但是,如果您已经有了工作代码,我只想添加一个变量bool restartRequested=false;

当用户请求重新启动时,设置restartRequested=true;并重置_mre。然后,如果restartRequested==true,则中断while循环并让线程方法完成。

您可以创建另一个手动重置事件,该事件只有在单击"重新启动"按钮时才会设置。以下是使用新的WaitHandle更新的代码。

threadStartingPoint() {
int index = 0;
//We have two waithandles that we need to wait on
var waitHandles = new WaitHandle[] {_mre, _restartMre};
while(index !== someMaxCondition)
      ... // grab some data to work on
      lock(_lock) {  // lock index, so one access at a time
        index += index;
      }
      ... // do some stuff
      //Wait on any one of the wait handles to signal
      WaitHandle.WaitAny(waitHandles);
      if (_restartMre.WaitOne(0)){
          break;
      }
    }
}