如何终止/退出/中止旧线程工作者并重启程序?

时间:2015-10-26 21:36:18

标签: c# multithreading

我有这些控制按钮(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()并创建新线程,有一段时间旧的线程仍将使用旧的数据循环。

有什么建议吗?

3 个答案:

答案 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;
      }
    }
}