I have these control buttons (Windows.Forms):
Start/Restart
| Pause
| Continue
Once Start
is pressed, threadPool[workerThreadsCount]
is created, ManualResetEvent mre
is set to mre.Set()
and threads start doing their job. In some pseudo-code:
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.
}
}
Worker threads work in a loop like in example above. Now if I press pause
, everything stop at _mre.Wait();
position. With continue
I can open gates using mre.Set()
and everything works just fine. Now the problem is when I Pause
, I want user to choose between Continue
or Restart
. The problem with Restart
is that I have no idea how to tell my threads to exit that while loop
. Because If I just set mre.Set()
and create new threads, for some time the old ones will still work with that old data loop.
Any suggestions?
Pass in a CancellationToken
and have it checked each loop.
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.
}
}
When the user clicks the Cancel button have it send a Cancel to the CancellationTokenSource
the tokens are derived from. Then new workers can just use a new Token Source that are unaffected by the previous cancelation.
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();
}
The "by the book" answer is to consider implementing a CancellationTokenSource .
But, if you already have working code, I would just add a variable bool restartRequested=false;
.
When the user then requests a restart, set restartRequested=true;
and reset the _mre
. Then break the while loop and let the thread method complete, if restartRequested==true
.
You could create another ManualResetEvent that gets set only when the "Restart" button is clicked. Here's the updated code using the new 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;
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.