另一个完成后运行BackgroundWorker

时间:2012-01-02 16:34:31

标签: c# backgroundworker multithreading

我希望在另一个完成之后开始BackgroundWorker。我不确定如何为它编写代码,所以我真的没有任何东西要显示。

我考虑过在RunWorkerCompleted中写一下,但这似乎是错误的地方,可以用来启动另一个工人。

我应该在哪里以及如何做到这一点?

基本上,我想使用同一个工人,但要做其他事情。与步骤1中的数据一样,它解析文件中的数据,在步骤2中,在步骤1完成后,它应该将解析后的数据从内存写入数据库。

5 个答案:

答案 0 :(得分:4)

您可以使用.NET 4.0 Task类,然后使用Task.ContinueWith排队更多工作。

答案 1 :(得分:3)

最好使用两个不同的BackgroundWorker组件。在第一个RunWorkerCompleted事件处理程序中启动第二个。这似乎是一种非常合理的做事方式。只是不要尝试使用单个BackgroundWorker

作为Tudor mentioned,您可以使用Task,但随后会失去BackgroundWorker的便利性,其中包含熟悉的面向事件的界面,进度报告等。

答案 2 :(得分:3)

从您的描述看来,步骤是相关的和顺序的,所以我将它实现为单个BGW,其中DoWork执行两个步骤,在解析步骤和写入之间调用ReportProgress到数据库步骤。

然后,您可以处理在UI线程上运行的ProgressChanged事件,以便在解析步骤完成后执行任何逻辑,因为知道该工作者已经在写入数据库。

ReportProgress接受一个整数来标识后台任务的完成百分比和可选的自定义对象。因此,在ProgressChanged处理程序中,您需要具有解释此进度信息的逻辑。在这种情况下,作为两步工作,您只需拨打ReportProgress(50)

答案 3 :(得分:1)

如果使用第三方库进行作业调度是可以接受的,请查看 Quartz.NET ,并在此处描述它的作业监听器机制http://quartznet.sourceforge.net/tutorial/lesson_7.html。如果你想自己实现它,我会使用一个BackgroundWorker来执行一系列组织成责任链的工作,你可以在这里阅读更多关于这个模式的信息{{ 3}}

答案 4 :(得分:0)

这将允许使用一名后台工作者进行多次后续操作:

    private void DoBackgroundWork<T>(string name, Func<T> work, Action<T> onComplete)
    {
        lblCurrentOperation.Text = name;
        StaticClass.OnProgress = (p) => backgroundWorker1.ReportProgress(p);
        T result = default(T);
        var handler = new DoWorkEventHandler((s, e) =>
        {
            result = work();
        });
        backgroundWorker1.DoWork += handler;

        RunWorkerCompletedEventHandler completedHandler = null;
        completedHandler = new RunWorkerCompletedEventHandler((s, e) =>
        {
            onComplete(result);
            backgroundWorker1.DoWork -= handler;
            backgroundWorker1.RunWorkerCompleted -= completedHandler;
            lblCurrentOperation.Text = string.Empty;
            progressBar1.Value = 0;
        });
        backgroundWorker1.RunWorkerCompleted += completedHandler;
    }

用法:

            DoBackgroundWork("Loading resources",
            () =>
            {
                return DoWork();
            },
            (result) =>
            {
                //final UI operations
                Task.Delay(500).ContinueWith(t => this.Invoke((Delegate)new Action(() => anotherOperationWithSameWorker())));
            });
        backgroundWorker1.RunWorkerAsync();