我来自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();
的方法中创建了workerprivate 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(它确实帮助我了解如何与代表合作)
答案 0 :(得分:0)
不要将UI表单传递给后台工作者,而是在UI表单中写入ProgressChanged。
因此,ProgressChanged(以及RunWorkerCompleted)也不能是worker的方法,因为你无法从另一个线程更新UI。