Say*_*yse 3 c# backgroundworker winforms
我正在使用后台工作人员来处理文件的加载以阻止我的 ui 冻结,但是似乎RunWorkerCompleted
在我的DoWork
事件完成之前就完成了(退出对话框时导致错误)......我做错了什么? 我最好在任务上做这个吗?
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();
}
Run Code Online (Sandbox Code Playgroud)
我相信这个问题可能归结为我的后台工作人员正在调用一个 dll 而不是等待响应的事实。我试图添加检查,如while(design == null)
无济于事..
Edit2 错误是 NRE,因为设计尚未加载,我可以轻松解决此问题,但宁愿让线程工作。
有很多小错误。鉴于我们可能没有查看真正的代码,并且我们没有带有调用堆栈窗口的调试器来查看它实际崩溃的位置,其中任何一个都可能是一个因素。
测试 bw.IsBusy 并且在它为真时不启动工作程序是一个严重的错误。它永远不会在发布的代码中忙碌,但如果它实际上可能为真,那么您的代码中就有一个令人讨厌的错误。因为您实际上确实订阅了忙碌工作人员的事件。现在 RunWorkerCompleted 事件处理程序将运行两次。
使用 Close() 方法关闭对话框是不正确的。应通过分配其 DialogResult 属性来关闭对话框。不是最严重的错误,但仍然是错误的。
代码中存在竞争,worker 可以在显示对话框之前完成。对话框只能在创建其本机窗口时关闭。换句话说,IsHandleCreated 必须为真。您必须将其联锁以确保永远不会发生这种情况。订阅对话框的 Load 事件以启动工作程序。
你盲目地假设工人会完成工作并产生结果。当它的 DoWork 方法因异常而死亡时,情况就不是这样了。它被 BackgroundWorker 捕获并作为 e.Error 属性传递给 RunWorkerCompleted 事件处理程序。如果它不为空,您必须检查此属性并做一些合理的事情。
从评论来看,我猜后一个子弹是原因。您可以通过使用 Debug + Exceptions 进行调试,为 CLR 异常选中 Throw 复选框。调试器现在将在抛出异常时停止,让您可以找出出错的地方。