C#后台工作者UI更新从类

时间:2016-09-13 12:34:09

标签: c# user-interface progress-bar backgroundworker

我来自java环境,最近才开始学习C#。

(请滚动问题的末尾以查看解决方案)

我尝试使用后台工作程序从Web服务中获取一些数据进行一些计算并更新UI,但我似乎无法让它报告进度

所以我的Form1.cc包含代表我的UI表单的MainForm类(包含2个日期选择器,1个进度条和一个按钮)。

在按钮上我绑定了以下点击处理程序:

private void runReport_Click(object sender, EventArgs e)

 private void runReport_Click(object sender, EventArgs e)
        {
            //MessageBox.Show("button pressed\n datefrom "+dateFrom.Value.ToString("yyyy-MM-dd" ));
            AdStage data=new AdStage(dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.ToString("yyyy-MM-dd"));
            //this.progressLabel.Text = "Fetching Data From Adstage";       
            //data.setUIProgressItems(progressLabel, this.progressBar);
            data.setUI(this);
            data.startWorker();
        }

在Adstage.cs上我有我所有的逻辑来处理后台工作人员。

 /*constructor*/
        public AdStage(String dateFrom, String dateTo)
        {
            //set the dates 
            setDates(dateFrom, dateTo);

        }
        public void startWorker()
        {
            doBg();//start bg worker...
        }

        public void setUI(MainForm ui)
        {
            this.ui = ui;
        }

 private void setDates(String dateFrom, String dateTo)
        {
            if (dateFrom.Equals(dateTo))
            {
                this.dateTo = this.dateTo = dateFrom;
            }
            else
            {
                this.dateFrom = dateFrom;
                this.dateTo = dateTo;
            }
        }

private void doRequest(String offset,String url= null,BackgroundWorker worker=null,int p=0)
    {
    //all of the logic that gets data from the web serivces is here
}



private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine(String.Format("worker_runWorkerCompleted"));
            //update ui once the job has finished..
            MessageBox.Show("Data Fetched! Total Campaigns: "+this.campaigns.Count());
            //this.ui.updateProgress("Fetched " + this.campaigns.Count() + " campaigns",100);
            //this.ui.progressLabel.Text = "Fetched "+this.campaigns.Count()+" campaigns";


        }

        public void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            Console.WriteLine("Testing worker_ProgressChanged: "+e.ProgressPercentage.ToString());
            MessageBox.Show("Progress: " + this.campaigns.Count());
            this.ui.progressLabel.Text = e.ProgressPercentage.ToString();
        }

这是我的DoWork功能

 private void worker_DoWork(object sender, DoWorkEventArgs e)
            {   
                Console.WriteLine(String.Format("worker_doWork"));
                //do all major background work here..   
                BackgroundWorker worker = sender as BackgroundWorker;
                worker.ReportProgress(1);
                doRequest(offset,null,worker);
                (worker as BackgroundWorker).ReportProgress(99, null);
                //worker.ReportProgress(100);
            }

所以即使是id,如果在doRequest()函数中使用报告进程,就像从未调用worker_ProgressChanged一样。工作人员继续,从Web服务获取所有页面,并且仅在完成时报告。 worker_ProgressChanged事件永远不会发生..

编辑:澄清我的代码,以帮助人们了解我在做什么:)

我在一个名为doBG();

的方法中创建了worker
private void doBg()
        {
            Console.WriteLine(String.Format("BG WORKER STARTED"));
            this.worker.DoWork += worker_DoWork;
            this.worker.RunWorkerCompleted += worker_RunWorkerCompleted;
            this.worker.WorkerReportsProgress = true;
            worker.RunWorkerAsync();
        }

单击buttn runReport时,我将创建一个Adstage类的实例。 (AdStage data=new AdStage(dateFrom.Value.ToString("yyyy-MM-dd"), dateTo.Value.ToString("yyyy-MM-dd"));

然后在那个实例上我设置了ui(这是我可以从Adstage类访问mainForm成员)

然后我通过调用data.startWorker()来从mainFOrm启动后台worker。 (基本上只调用Adstage类的doBG()函数)。这是因为我已将doBG()设置为Adstage类上的私有。

编辑2: 在doBg()函数中添加this.worker.ProgressChanged += worker_ProgressChanged;似乎可以解决这个问题,谢谢Dirk指出这一点并感谢机器学习提供了很好的建议:)

对于有相同问题的任何人,您也可以使用委托更新ui。 请在此处查看此答案以了解如何执行此操作:https://stackoverflow.com/a/3303276/514657(它确实帮助我了解如何与代表合作)

1 个答案:

答案 0 :(得分:0)

不要将UI表单传递给后台工作者,而是在UI表单中写入ProgressChanged。

因此,ProgressChanged(以及RunWorkerCompleted)也不能是worker的方法,因为你无法从另一个线程更新UI。