5

有没有办法直接“重启”后台工作人员?调用 CancelAsync() 后跟 RunWorkerAsync() 显然不会像他们的名字所暗示的那样做。

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

4

5 回答 5

11

背景工作本身不做任何取消。

当您调用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;
    }

}
于 2009-06-17T07:11:11.233 回答
2

有几种选择,这完全取决于你想如何给这只猫剥皮:

如果你想继续使用BackgroundWorker,那么你需要尊重已经建立的模型,即“进度敏感性”之一。里面的东西DoWork显然需要始终知道挂起的取消是否到期(即,需要在DoWork循环中进行一定数量的轮询)。

如果您的计算代码是单一的并且您不想弄乱它,那么不要使用BackgroundWorker,而是启动您自己的线程——这样您可以在需要时强行杀死它。

于 2009-06-17T07:17:35.340 回答
0

您可以挂钩更改值的控件的更改事件处理程序,并在处理程序中执行以下操作:

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

希望对你有帮助!

于 2009-06-17T07:13:43.227 回答
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);
    }
于 2014-07-30T22:57:43.837 回答
0

可以这种方法帮助某人...我创建了一个函数来以一种方法重置后台工作人员。我将它用于定期执行的任务。

通过创建一个Task,可以使用 停止后台工作程序CancelAsync并在任务内重新启动。正如 OP 所描述的,在取消任务之前,不创建任务将再次启动后台工作程序。

唯一的要求是您的代码通过某个循环运行,该循环在每个时间段 ( CheckPerMilliseconds) 中检查 CancellationPending。

private void ResetBackgroundWorker()
{
    backgroundWorker.CancelAsync();

    Task taskStart = Task.Run(() => 
    {
        Thread.Sleep(CheckPerMilliseconds);
        backgroundWorker.RunWorkerAsync();
    });
}

在 backgroundworker 中,我使用了一个检查 CancellationPending 的 for 循环。

private void BackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    BackgroundWorker worker = sender as BackgroundWorker;

    while(true)
    {
        if (backgroundWorker.CancellationPending)
        {
            return;
        }

        //Do something you want to do periodically.

        for (int i = 0; i < minutesToDoTask * 60; i++)
        {
            if (backgroundWorker.CancellationPending)
            {
                return;
            }

            Thread.Sleep(CheckPerMilliseconds);
        }
    }
}
于 2020-01-08T10:17:38.857 回答