我有这些控制按钮(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()
并创建新线程,有一段时间旧的线程仍将使用旧的数据循环。
有什么建议吗?
答案 0 :(得分:2)
传入CancellationTokenSource
并检查每个循环。
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.
}
}
当用户点击“取消”按钮时,它会向How to change the interaction mode (XAML)发送取消,从中派生出令牌。然后,新工作人员可以使用不受先前取消影响的新令牌源。
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();
}
答案 1 :(得分:0)
"书"答案是考虑实施CancellationTokenSource。
但是,如果你已经有了工作代码,我只想添加一个变量bool restartRequested=false;
。
当用户请求重新启动时,请设置restartRequested=true;
并重置_mre
。然后打破while循环并让线程方法完成,如果restartRequested==true
。
答案 2 :(得分:0)
您可以创建另一个仅在"重新启动"时才设置的ManualResetEvent。单击按钮。 这是使用新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;
}
}
}