BackgroundWorker OnWorkCompleted 抛出跨线程异常 [英] BackgroundWorker OnWorkCompleted throws cross-thread exception

查看:36
本文介绍了BackgroundWorker OnWorkCompleted 抛出跨线程异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用于数据库分页的简单 UserControl,它使用控制器来执行实际的 DAL 调用.我使用 BackgroundWorker 来执行繁重的工作,并在 OnWorkCompleted 事件上重新启用一些按钮,更改 TextBox.Text 属性和为父表单引发事件.

I have a simple UserControl for database paging, that uses a controller to perform the actual DAL calls. I use a BackgroundWorker to perform the heavy lifting, and on the OnWorkCompleted event I re-enable some buttons, change a TextBox.Text property and raise an event for the parent form.

Form A 包含我的 UserControl.当我点击某个打开表单 B 的按钮时,即使我没有在那里"做任何事情并关闭它,并尝试从我的数据库中引入下一页,OnWorkCompleted 也会被调用在工作线程(而不是我的主线程)上,并引发跨线程异常.

Form A holds my UserControl. When I click on some button that opens form B, even if I don't do anything "there" and just close it, and try to bring in the next page from my database, the OnWorkCompleted gets called on the worker thread (and not my Main thread), and throws a cross-thread exception.

目前我在那里的处理程序中添加了对 InvokeRequired 的检查,但是 OnWorkCompleted 的全部意义不是要在主线程上调用吗?为什么它不能按预期工作?

At the moment I added a check for InvokeRequired at the handler there, but isn't the whole point of OnWorkCompleted is to be called on the Main thread? Why wouldn't it work as expected?

我已设法将问题缩小到 arcgis 和 BackgroundWorker.我有以下解决方案,它向 arcmap 添加了一个命令,它打开一个带有两个按钮的简单 Form1.

I have managed to narrow down the problem to arcgis and BackgroundWorker. I have the following solution wich adds a Command to arcmap, that opens a simple Form1 with two buttons.

第一个按钮运行一个 BackgroundWorker,它会休眠 500 毫秒并更新一个计数器.在 RunWorkerCompleted 方法中,它检查 InvokeRequired,并更新标题以显示该方法最初是在主线程还是工作线程中运行.第二个按钮只是打开 Form2,其中不包含任何内容.

The first button runs a BackgroundWorker that sleeps for 500ms and updates a counter. In the RunWorkerCompleted method it checks for InvokeRequired, and updates the title to show whethever the method was originaly running inside the main thread or the worker thread. The second button just opens Form2, which contains nothing.

首先,所有对 RunWorkerCompletedare 的调用都是在主线程内进行的(正如预期的那样 - 这就是 RunWorkerComplete 方法的重点,至少我从 MSDN BackgroundWorker)

At first, all the calls to RunWorkerCompletedare are made inside the main thread (As expected - thats the whold point of the RunWorkerComplete method, At least by what I understand from the MSDN on BackgroundWorker)

在打开和关闭 Form2 之后,总是在工作线程上调用 RunWorkerCompleted.我想补充一点,我可以将这个解决方案保留原样(检查 RunWorkerCompleted 方法中的 InvokeRequired),但我想了解为什么会发生这种情况我的期望.在我的真实"代码中,我想始终知道 RunWorkerCompleted 方法正在主线程上被调用.

After opening and closing Form2, the RunWorkerCompleted is always being called on the worker thread. I want to add that I can just leave this solution to the problem as is (check for InvokeRequired in the RunWorkerCompleted method), but I want to understand why it is happening against my expectations. In my "real" code I'd like to always know that the RunWorkerCompleted method is being called on the main thread.

我设法在我的 BackgroundTesterBtn 中的 form.Show(); 命令中找出问题 - 如果我使用 ShowDialog()相反,我没有问题(RunWorkerCompleted 总是在主线程上运行).我确实需要在 ArcMap 项目中使用 Show(),这样用户就不会绑定到表单.

I managed to pin point the problem at the form.Show(); command in my BackgroundTesterBtn - if I use ShowDialog() instead, I get no problem (RunWorkerCompleted always runs on the main thread). I do need to use Show() in my ArcMap project, so that the user will not be bound to the form.

我还尝试在普通 WinForms 项目上重现该错误.我添加了一个简单的项目,它只是在没有 ArcMap 的情况下打开第一个表单,但在那种情况下我无法重现该错误 - RunWorkerCompleted 在主线程上运行,无论我是否使用了 Show()ShowDialog(),在打开 Form2 之前和之后.我尝试在我的 Form1 之前添加第三个表单作为主表单,但它没有改变结果.

I also tried to reproduce the bug on a normal WinForms project. I added a simple project that just opens the first form without ArcMap, but in that case I couldn't reproduce the bug - the RunWorkerCompleted ran on the main thread, whether I used Show() or ShowDialog(), before and after opening Form2. I tried adding a third form to act as a main form before my Form1, but it didn't change the outcome.

这里是我的简单 sln (VS2005sp1) - 它需要

Here is my simple sln (VS2005sp1) - it requires

ESRI.ArcGIS.ADF(9.2.4.1420)

ESRI.ArcGIS.ADF(9.2.4.1420)

ESRI.ArcGIS.ArcMapUI(9.2.3.1380)

ESRI.ArcGIS.ArcMapUI(9.2.3.1380)

ESRI.ArcGIS.SystemUI (9.2.3.1380)

ESRI.ArcGIS.SystemUI (9.2.3.1380)

推荐答案

看起来像是一个错误:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=116930

http://thedatafarm.com/devlifeblog/archive/2005/12/21/39532.aspx

所以我建议使用防弹(伪代码):

So I suggest using the bullet-proof (pseudocode):

if(control.InvokeRequired)
  control.Invoke(Action);
else
  Action()

这篇关于BackgroundWorker OnWorkCompleted 抛出跨线程异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆