在我的winforms项目中,我得到了一些运行BackgroundWorker的Form。基本上它是一个模拟,所以它可以在某个时候解决,但也可以由用户停止,所以当它完成任何一种方式时,它需要重绘结果。我遇到了一个问题,即当我关闭主窗口时它的引用为null,但BW仍然可以触发ReportProgress,最终会出现异常。
我的BackgroundWorker(简化代码):
void backgroundWorkerRunSimulation_DoWork(object sender, DoWorkEventArgs e)
{
bool ShouldContinue = true;
do
{
SomeHeavyComputing();
if(CheckIfSimulationDone() | backgroundWorkerRunSimulation.CancellationPending)
ShouldContinue=false;
//Redrawing results on the interface
if (AlwaysRefresh | !ShouldContinue)
UpdateGUI(); //<--Method invoked on form's thread
//Reporting progress
backgroundWorkerRunSimulation.ReportProgress(0, SomeReportingObject);
}
while(ShouldContinue);
}
和ReportProgress:
private void backgroundWorkerRunSimulation_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
UpdateStatusBar((GUIReportInfo)e.UserState);//<-also invoked on form's thread
}
其中
void UpdateStatusBar(GUIReportInfo ReportInfo)
{
if (this.InvokeRequired)
{
ReportInfoDelegate updateStatusBar = new ReportInfoDelegate(UpdateStatusBar);
this.Invoke(updateStatusBar, new object[] { ReportInfo });
}
else
//Some assignments on form - crashes here, null reference exc
}
显然不应该启动UpdateStatusBar,我很惊讶UpdateGUI(这是类比的)不会崩溃。但有没有办法检查表格是否仍然存在? 添加:
this.Invoke(new MethodInvoker(delegate { this.Close(); }));
到FormClosing事件似乎解决了这个问题,虽然我不明白为什么会这样。是不是在表单的线程上激活了Close()方法?
我很乐意帮助你。
答案 0 :(得分:1)
我猜测添加的调用只是偶然改变了事件的顺序,所以它不会崩溃。优雅的解决方案是实现FormClosing并在那里中止BW,并等待它直到完成。此外,在BW代码中,您应该检查“CancellationPending”。更多信息:
http://msdn.microsoft.com/en-us/library/hybbz6ke.aspx
编辑: 这里最高投票的答案证明了解决方案: How to stop BackgroundWorker on Form's Closing event?
答案 1 :(得分:0)
我已经设法通过等待带有计时器的工人来解决我的问题。
void FormMain_FormClosing(object sender, FormClosingEventArgs e)
{
if (backgroundWorkerSimulationRunMany.IsBusy)
{
backgroundWorkerSimulationRunMany.CancelAsync();
e.Cancel = true;
timerDelayQuit.Start();
}
}
private void timerQuitDelay_Tick(object sender, EventArgs e)
{
timerDelayQuit.Stop();
this.Close();
}