BackgroundWorker取消 [英] BackgroundWorker cancellation

查看:85
本文介绍了BackgroundWorker取消的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在winforms应用程序中使用BackgroundWorker来执行另一个类中发生的长时间运行的任务(执行数据库操作).由于所有工作都是在另一个类中完成的,因此取消并不是那么简单.我在另一个类(GenerateStats)中使用一个事件在后台操作完成时更新进度.我想通过取消操作来做类似的事情.我不能只在DoWork函数中调用cancellationPending,因为该方法要等到它完成并且无法达到目的时才能看到它.我想要取消功能,而不必将BackgroundWorker传递给generateForSubject().无论如何,这是否可以支持从GenerateStats类中的generateForSubject()方法取消.这是操作在其中执行的类的实例:

I am using a BackgroundWorker in my winforms app to perform a long running task that occurs in another class (performing database operations). Since all the work is done in another class the cancellation is not as simple. I am using an event in the other class (GenerateStats) to update the progress as the background operation completes. I want to do a similar thing with cancelling the operation. I can't just call cancellationPending in the DoWork function because the method would never see it until it finishes and that defeats the purpose. I want the cancellation functionality without having the pass the BackgroundWorker to generateForSubject(). Is there anyway that this can support cancellation from the generateForSubject() method in GenerateStats class. This is the instantiation of the class that the operation performs in:

GenerateStats genStats = new GenerateStats();

这是我的DoWork函数,每当调用另一个类中的事件时,该函数就会调用ReportProgress方法.它还从另一个执行操作的类generateForSubject()中调用该方法.

This is my DoWork function, which calls the ReportProgress method anytime the event in the other class gets called. It also calls the method from the other class generateForSubject() that performs the operations.

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

    genStats.ProgressChanged += (s, pe) => worker.ReportProgress(pe.ProgressPercentage, pe.UserState);
    genStats.generateForSubject();
}

这是按钮单击事件处理程序,应启动取消并运行CancelAsync()

This is the button click event handler that should initiate the cancellation and run CancelAsync()

private void btnStop_Click(object sender, EventArgs e)
{
    if (backgroundWorker.IsBusy)
    {
        backgroundWorker.CancelAsync();
    }
}

这是我执行操作的单独类,同时创建ProgressChanged事件处理程序,因此我的类可以使用进度信息更新表单.如果取消的执行方式相似,那就太棒了.

This is my separate class that performs the operation, along with creating the ProgressChanged event handler so my class can updated the form with info on progress. It would be awesome if cancellation can perform similarly.

public event ProgressChangedEventHandler ProgressChanged;

protected virtual void OnProgressChanged(int progress, string message)
{
    if (ProgressChanged != null)
    {
        ProgressChanged(this, new ProgressChangedEventArgs(progress, message));
    }
}

public void generateForSubject()
{
    //Perform db operation not important, but it takes time

    OnProgressChanged(33, "Finished 1st set of stats");
    //I hope to check for cancellation here

    //Perform db operation not important, but it takes time

    OnProgressChanged(66, "Finished 2nd set of stats");
    //I hope to check for cancellation here        

    //Perform db operation not important, but it takes time

    OnProgressChanged(99, "Finished 3rd set of stats");
    //I hope to check for cancellation here
}

只是为了弄清楚我要问的内容是否存在不确定性,我有什么方法可以支持取消其他类中的backgroundWorker而无需将backgroundWorker传递给该方法.如果绝对没有办法,而且我必须这样做,那么我将通过backgroundWorker

Just to clarify if there is any uncertainty as to what I am asking, is there any way for me to support cancellation of my backgroundWorker in the other class without passing the backgroundWorker to the method. If there is absolutely no way and I have to, then I will pass the backgroundWorker

推荐答案

如果您更具体地表示不愿意通过BackgroundWorker实例,这将对您有所帮助.知道为什么这是设计要求,可以帮助您更好地回答问题.

It would be helpful if you could be more specific about your reluctance to pass the BackgroundWorker instance. Knowing why that's a design requirement could help produce a better answer to your question.

也就是说,您可以应用与ProgressChanged事件相同的理念,也可以委派取消检查.例如:

That said, you can apply the same philosophy you did for the ProgressChanged event and delegate the cancellation check as well. For example:

class GenerateStats
{
    public event EventHandler<CancelEventArgs> CheckCancel;

    private bool OnCheckCancel()
    {
        EventHandler<CancelEventArgs> handler = CheckCancel;

        if (handler != null)
        {
            CancelEventArgs e = new CancelEventArgs();

            handler(this, e);

            return e.Cancel;
        }

        return false;
    }

    public void generateForSubject()
    {
        //Perform db operation not important, but it takes time

        OnProgressChanged(33, "Finished 1st set of stats");
        if (OnCheckCancel())
        {
            // Or other cancellation logic here
            return;
        }

        //Perform db operation not important, but it takes time

        OnProgressChanged(66, "Finished 2nd set of stats");
        if (OnCheckCancel())
        {
            // Or other cancellation logic here
            return;
        }

        //Perform db operation not important, but it takes time

        OnProgressChanged(99, "Finished 3rd set of stats");
        if (OnCheckCancel())
        {
            // Or other cancellation logic here
            return;
        }
    }
}

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

    genStats.ProgressChanged += (s, pe) => worker.ReportProgress(pe.ProgressPercentage, pe.UserState);
    genStats.CheckCancel += (sender1, e1) => e1.Cancel = worker.CancellationPending;
    genStats.generateForSubject();
}

这允许GenerateStats类检查挂起的取消而无需直接访问BackgroundWorker实例,就像ProgressChanged事件允许它通过BackgroundWorker报告进度而无需直接访问.

This allows the GenerateStats class to check for pending cancellation without having direct access to the BackgroundWorker instance, just as the ProgressChanged event allows it to report progress via the BackgroundWorker without direct access to the BackgroundWorker.

这篇关于BackgroundWorker取消的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆