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