我有一个用于数据库分页的简单 UserControl,它使用控制器来执行实际的 DAL 调用。我使用 aBackgroundWorker来执行繁重的工作,并在OnWorkCompleted事件中重新启用某些按钮、更改TextBox.Text属性并为父表单引发事件。
表单 A 包含我的用户控件。当我单击打开表单 B 的某个按钮时,即使我没有在“那里”做任何事情并关闭它,并尝试从我的数据库中引入下一页,OnWorkCompleted在工作线程(而不是我的主线程),并引发跨线程异常。
目前我InvokeRequired在那里的处理程序处添加了一个检查,但不是OnWorkCompleted要在主线程上调用整个点吗?为什么它不能按预期工作?
编辑:
我设法将问题缩小到 arcgis 和BackgroundWorker. 我有以下解决方案,它向 arcmap 添加了一个命令,Form1用两个按钮打开一个简单的命令。
第一个按钮运行BackgroundWorker睡眠 500 毫秒并更新计数器。在RunWorkerCompleted方法中它检查InvokeRequired并更新标题以显示该方法最初是在主线程还是在工作线程中运行。第二个按钮刚刚打开Form2,其中不包含任何内容。
起初,所有的调用RunWorkerCompletedare都是在主线程内进行的(正如预期的那样——这就是 RunWorkerComplete 方法的全部要点,至少我从MSDN上了解到的BackgroundWorker)
在打开和关闭之后Form2,RunWorkerCompleted总是在工作线程上被调用。我想补充一点,我可以让这个问题的解决方案保持原样(InvokeRequired在RunWorkerCompleted方法中检查),但我想了解为什么它会违背我的期望。在我的“真实”代码中,我想始终知道该RunWorkerCompleted方法是在主线程上调用的。
我设法form.Show();在我的命令中指出问题BackgroundTesterBtn- 如果我ShowDialog()改用,我没有问题(RunWorkerCompleted总是在主线程上运行)。我确实需要Show()在我的 ArcMap 项目中使用,这样用户就不会被绑定到表单。
我还尝试在普通的 WinForms 项目中重现该错误。我添加了一个简单的项目,它只打开没有 ArcMap 的第一个表单,但在那种情况下,我无法重现错误 - 在RunWorkerCompleted主线程上运行,无论是我使用Show()还是ShowDialog()打开之前和之后Form2。我尝试在 my 之前添加第三种形式作为主要形式Form1,但它并没有改变结果。
这是我的简单 sln (VS2005sp1) - 它需要
ESRI.ArcGIS.ADF(9.2.4.1420)
ESRI.ArcGIS.ArcMapUI(9.2.3.1380)
ESRI.ArcGIS.SystemUI (9.2.3.1380)