重新启动后台工作者

发布于 2024-07-24 23:19:54 字数 204 浏览 5 评论 0原文

有没有办法直接“重启”后台工作者? 调用 CancelAsync() 再调用 RunWorkerAsync() 显然不会像其名称所暗示的那样执行此操作。

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

Is there a way to directly "restart" a background worker?
Calling CancelAsync() followed by RunWorkerAsync() clearly won't do it as their names imply.

Background info:
I have a background worker which calculates a total in my .net 2.0 Windows Forms app.
Whenever the user modifies any value which is part of this total I'd like to restart the background worker in case it would be running so that directly the latest values are considered.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

故人如初 2024-07-31 23:19:54

背景工作本身不会进行任何取消。

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

}

The backgriound work itself does not do any cancleing.

When you call bgw.CancelAsync it sets a flag on the background worker that you need to check yourself in the DoWork handler.

something like:

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

}
北音执念 2024-07-31 23:19:54

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

如果你想继续使用BackgroundWorker,那么你需要尊重已经建立的模型,即“进步敏感性”之一。 DoWork 中的内容显然需要始终了解挂起的取消是否到期(即,您的 DoWork 中需要进行一定量的轮询)代码>循环)。

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

There are a couple of options, it all depends on how you want to skin this cat:

If you want to continue to use BackgroundWorker, then you need to respect the model that has been established, that is, one of "progress sensitivity". The stuff inside DoWork is clearly required to always be aware of whether or not the a pending cancellation is due (i.e., there needs to be a certain amount of polling taking place in your DoWork loop).

If your calculation code is monolithic and you don't want to mess with it, then don't use BackgroundWorker, but rather fire up your own thread--this way you can forcefully kill it if needs be.

-残月青衣踏尘吟 2024-07-31 23:19:54

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

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

希望它对您有帮助!

You can hook the change event handler for the controls in which the values are changed and do the following in the handler:

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

Hope it helps you!

脸赞 2024-07-31 23:19:54

我想让我的请求继续运行,但不再关心结果。 我覆盖了后台工作人员的值(我的繁忙微调器正在使用 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);
    }

I want to leave my requests running, but no longer care about the results. I override the value of the background worker (my busy spinner is using the isBusy flag).

    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);
    }
狂之美人 2024-07-31 23:19:54

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

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

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

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

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

在后台工作程序中,我使用一个 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);
        }
    }
}

May this method help someone... I've created a function to reset the backgroundworker in one method. I use it for task to do periodically.

By creating a Task, the backgroundworker is can be stopped with the CancelAsync and restarted inside the Task. Not making a Task wil start the backgroundworker again before it is cancelled, as the OP describes.

The only requirement is that your code runs through some loop, which checks the CancellationPending every period of time (CheckPerMilliseconds).

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

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

Inside the backgroundworker I use a for-loop that checks the CancellationPending.

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);
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文