如何终止/退出/中止旧的线程工作程序并重新启动程序
本文关键字:线程 工作程序 程序 重新启动 何终止 终止 退出 | 更新日期: 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
时,我希望用户在Continue
或Restart
之间进行选择。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;
}
}
}