函数第一次运行正常,但第二次生成2个窗口而不是一个窗口

时间:2014-02-25 20:35:28

标签: c# backgroundworker

此代码的目的是接受表单中的文本,将其传递给函数,并将此文本存储在将执行第二个函数的后台工作程序中。此后台工作程序已定义其do_work和work_completed事件侦听器。问题是当我第一次运行应用程序运行此代码时,它工作正常。下次我执行“fetchFunction”并随后执行fetchStuff函数时,我得到2个窗口或2个objfrmMChild,而不是像我第一次运行它时那样。

我在调试模式下运行我的代码并看到RunWorkerCompletedEventHandler运行一次然后弹出窗口,然后它再次循环并再次运行。知道为什么吗?

     public void fetchFunction(TextBox text)
     {
        fetch.WorkerSupportsCancellation = true;

        if (!fetch.IsBusy)
        {
            Lists.BGWParams bgwp = new Lists.BGWParams();
            bgwp.Value = text.Text.Trim();
            fetchStuff(bgwp);
        }

        else
        {
            fetch.CancelAsync();
        }
    }


    private void fetchStuff(Lists.BGWParams parameters)
    {
        DoWorkEventHandler dweh = (object senderA, DoWorkEventArgs argsA) =>
        {
            if (argsA != null && argsA.Argument is Lists.BGWParams)
            {
                Lists.BGWParams p = argsA.Argument as Lists.BGWParams;
                p.Result2 = genericClass.fetchOtherStuff_DoWork(p.Value);            
                argsA.Result = argsA.Argument;
            }
        };

        RunWorkerCompletedEventHandler rwceh = (object senderB, RunWorkerCompletedEventArgs argsB) =>
        {
            if (argsB != null && argsB.Result is Lists.BGWParams)
            {
                Lists.BGWParams p = argsB.Result as Lists.BGWParams;
                frmMChild objfrmMChild = new frmMChild(this);

                countResults = p.Result2;
                objfrmMChild.MdiParent = this;
                objfrmMChild.Show();
                objfrmMChild.populateDataGridwithStuff(p.Result2, p.Value);
            }
        };

        fetch.DoWork += dweh;
        fetch.RunWorkerCompleted += rwceh;

        fetch.RunWorkerAsync(parameters);
    }

1 个答案:

答案 0 :(得分:2)

您的fetchStuff正在引用作为实例字段的BackgroundWorker。每次调用fetchStuff时,您都会为每个事件添加另一个处理程序。第一次有一次,第二次有两次,第三次有三次。你多次做这项工作,并多次显示结果。

只需将BGW置于该方法的本地。如果您每次没有这个问题就创建一个新的BGW。如果你这样做,你仍然需要支持取消。最简单的方法是创建一个CancellationTokenSource作为BGW使用的字段。每次开始操作时都创建一个新的CTS。 (也就是说,您从未在DoWork处理程序中检查取消,因此您实际上并未取消任何内容。)

另一种方法是在创建此类时附加这些事件处理程序,而不是在fetchStuff内部; fetchStuff只需致电RunWorkerAsync。 (或者就此而言,完全省略它,并且可以调用它RunWorkeAsync。)