2015-10-26 62 views
0

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

有什么建议吗?

+0

您需要使用具有超时值的'WaitOne'的重载。然后在while测试条件下,测试一些暂停或退出条件。 – GreatAndPowerfulOz

+0

fyi'index'是线程本地的,你不需要锁定它,因为只有一个线程可以触摸它。 –

回答

0

“按书”答案是考虑实施CancellationTokenSource

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

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

+0

由于访问数据时的波动性,多线程中不建议使用简单变量。 http://www.yoda.arachsys.com/csharp/threads/printable.shtml – Don

+0

@DonJayamanne,通常我会同意你的看法。但是,这段代码已经在WaitHandle上停止了。这里波动不是问题。 – bigtlb

2

传入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. 
    } 
} 

当用户点击取消按钮具有其发送一个取消到CancellationTokenSource令牌衍生自。然后,新工作人员可以使用不受先前取消影响的新令牌来源。

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(); 
} 
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; 
     } 
    } 
} 
相关问题