2009-06-17 112 views
4

有没有办法直接“重新启动”后台工作人员? 调用CancelAsync()后跟RunWorkerAsync()显然不会按照它们的名字暗示。重新启动后台工作人员

背景信息: 我有一个后台工作人员,它可以计算我的.net 2.0 Windows窗体应用程序中的总数。 每当用户修改任何属于此总数的值时,我想重新启动后台工作程序,以防将其运行以便直接考虑最新值。

回答

6

后退工作本身不做任何可以清理。

当您拨打bgw.CancelAsync时,它会在后台工作人员上设置一个标志,您需要在DoWork处理程序中检查自己。

类似:

bool _restart = false; 

private void button1_Click(object sender, EventArgs e) 
{ 
    bgw.CancelAsync(); 
    _restart = true; 
} 

private void bgw_DoWork(object sender, DoWorkEventArgs e) 
{ 

    for (int i = 0; i < 300; i++) 
    { 
     if (bgw.CancellationPending) 
     { 
      break; 
     } 
     //time consuming calculation 
    } 
} 

private void bgw_WorkComplete(object sender, eventargs e) //no ide to hand not sure on name/args 
{ 
    if (_restart) 
    { 
     bgw.RunWorkerAsync(); 
     _restart = false; 
    } 

} 
+1

我对此非常了解。问题是关于是否有其他机制允许直接(强制?)退出并重新启动后台工作者。 – Marc 2009-06-17 09:58:58

+1

这不是你的问题所暗示的。不,没有,正如Eric所说,你只需要使用一个线程并手动中止。 – Pondidum 2009-06-17 10:19:48

0

您可以挂钩的控件的change事件处理程序中的值被改变,而在处理程序如下:

if(!bgWrkr.IsBusy) 
    //start worker 
else if(!bgWrkr.CancellationPending) 
    bgWrkr.CancelAsync(); 

希望它可以帮助你!

+1

这并不能解决问题,只是概括了它:如果我在你的例子中调用了CancelAsync(),那么后台工作者将不会重新启动以重新计算最新值。在CancelAsync()之后调用RunWorkerAsync()也不能解决问题,因为取消是异步处理的...... – Marc 2009-06-17 10:01:27

2

有几个选项,这一切都取决于你想如何皮肤这只猫:

如果你想继续使用BackgroundWorker,那么你需要尊重已经建立的模式,即,“进步敏感度”之一。 DoWork中的内容显然需要始终注意是否有未决的取消请求(即需要在您的DoWork循环中进行一定数量的轮询)。

如果你的计算代码是单片的,你不想惹它,那就不要使用BackgroundWorker,而是开启你自己的线程 - 这样你可以在需要的时候强行杀死它。

0

我想让我的请求继续运行,但不再关心结果。我重写后台工作的值(我的忙碌微调正在使用isBusy标志)。

private void SearchWorkerCreate() { 
     this.searchWorker = new BackgroundWorker(); 
     this.searchWorker.DoWork += this.SearchWorkerWork; 
     this.searchWorker.RunWorkerCompleted += this.SearchWorkerFinish; 
    } 

    private void SearchWorkerStart(string criteria){ 
     if(this.searchWorker.IsBusy){ 
      this.SearchWorkerCreate(); 
     } 
     this.searchWorker.RunWorkerAsync(criteria); 
     this.OnPropertyChanged(() => this.IsBusy); 
     this.OnPropertyChanged(() => this.IsIdle); 
    }