BackgroundWorker在DoWork之前完成

时间:2013-05-29 07:50:23

标签: c# winforms backgroundworker

我正在使用后台工作程序来处理文件加载以阻止我的ui冻结,但似乎RunWorkerCompletedDoWork事件完成之前完成(退出时导致错误)对话)...有什么我做错的吗?我最好不要在任务中做这件事吗?

public static <T> LoadDesign(string xmlPath)
{
    PleaseWait pw = new PleaseWait(xmlPath);
    pw.ShowDialog();
    return pw.design;
}


private PleaseWait(string xmlFile)
{
   InitializeComponent();
   bw = new BackgroundWorker();
   bw.WorkerSupportsCancellation = true;
   bw.DoWork += (s, e) =>
   {
      design = (Cast)DllCall containing XmlSerializer.Deserialize(...,xmlFile);
   };
   bw.RunWorkerCompleted += (s, e) => {
   //Exit please wait dialog
      this.Close(); 
   };
   if (!bw.IsBusy)
       bw.RunWorkerAsync();
}

我认为这个问题可能是由于我的后台工作者正在调用dll而不是等待响应。我试图添加诸如while(design == null)之类的检查无效......

EDIT2 错误是NRE,因为设计尚未加载,我可以轻松解决这个问题,但宁愿让线程工作。

2 个答案:

答案 0 :(得分:4)

有很多小错误。鉴于我们可能没有查看真正的代码,并且我们没有带调用堆栈窗口的调试器来查看它实际崩溃的位置,其中任何一个都可能是一个因素。

  • 测试bw.IsBusy和启动工作人员是真的是一个严重的错误。它不会像发布的那样忙于代码,但如果它确实可能是真的那么你的代码中就会有一个讨厌的错误。因为你实际上 订阅繁忙的工作人员的事件。现在,RunWorkerCompleted事件处理程序将运行两次。

  • 使用Close()方法关闭对话框不正确。应通过分配DialogResult属性来关闭对话框。不是最严重的错误,但仍然是错误的。

  • 代码中存在争用,工作人员可以在对话框显示之前完成。只能在创建其本机窗口时关闭对话框。换句话说,IsHandleCreated必须为true。您必须将其联锁以确保永远不会发生这种情况。订阅对话框的Load事件以启动工作程序。

  • 你盲目地认为工人会完成工作并产生结果。当DoWork方法因异常而死时,情况就不会如此。它由BackgroundWorker捕获并作为e.Error属性传递给RunWorkerCompleted事件处理程序。您必须检查此属性,如果它不为空,则执行合理的操作。

从评论来看,我猜测后一个子弹是原因。您可以使用Debug + Exceptions调试此项,勾选CLR异常的Thrown复选框。抛出异常时调试器现在会停止,让你找出出错的地方。

答案 1 :(得分:1)

在显示对话框之前,你的后台工作人员可能不会花费太多时间和完成。我建议将后台工作程序初始化和启动代码转移到PleaseWait的Form_Load或Form_Shown