我有一个用于数据库分页的简单 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)