奇怪的跨线程UI错误 [英] Strange cross-threading UI errors

查看:160
本文介绍了奇怪的跨线程UI错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个WinForms应用程序,它有两种模式:控制台或GUI。在同一解决方案中的三个项目,一个控制台应用程序,一个用于UI形式和三分之一认为这两个接口都将连接过的逻辑。控制台应用程序运行流畅绝。

I'm writing a WinForms app which has two modes: console or GUI. Three projects within the same solution, one for the console app, one for the UI forms and the third to hold the logic that the two interfaces will both connect too. The Console app runs absolutely smoothly.

持有用户选择一种模式,它有一个的IList< T> ,其中T是一个本地对象,步骤,它实现了 INotifyPropertyChanged的,所以在这个被安装到一个DataGridView的用户界面。所有在运行时细,对象的初始状态被反射在屏幕上。

A model which holds the user-selections, it has an IList<T> where T is a local object, Step, which implements INotifyPropertyChanged, so in the UI this is mounted on to a DataGridView. All is fine at runtime, the initial state of the objects is reflected on the screen.

每个对象是依次执行的任务;一些属性会发生变化,被反射回的IList并传递到DataGridView。

Each of the Step objects is a task which is performed in turn; some of the properties will change, being reflected back to the IList and passed on to the DataGridView.

在UI版本的这一行动是通过创建一个BackgroundWorker的筹款活动回到UI完成。在步骤做这件事,并生成一个 StepResult 对象,它是一个枚举类型指示的结果(如跑步,NotRun, OK,NotOK,买者)和一个字符串来表示信息(因为步运行,但如预期不大,也就是一个警告)。通常情况下,行动会涉及到数据库交互,但在调试模式下我随机生成的结果。

This action in the UI versions is done by creating a BackgroundWorker raising events back to the UI. The Step does it thing and generates a StepResult object which is an enumerated type indicating a result (e.g. Running, NotRun, OK, NotOK, Caveat) and a string to indicate a message (because the step ran but not quite as expected, i.e. with a Caveat). Normally the actions will involve a database interaction, but in debug mode I randomly generate a result.

如果该消息为null,从未有一个问题,但如果我产生这样的回应:

If the message is null, there's never a problem, but if I generate a response like this:

StepResult returnvalue = new StepResult(stat, "completed with caveat")

我得到一个错误,指出在DataGridView正在从比它创建的线程以外的线程访问。 (我通过这个经过必要时,应处理调用自定义的处理器 - 也许事实并非如此)

I get an error saying that the DataGridView was being accessed from a thread other than the thread it was created on. (I'm passing this through a custom handler which should handle the invoking when required - maybe it doesn't?)

然后,如果我生成一个独特的反应,例如使用随机数研究

Then if I generate a unique response, e.g. using a random number r:

StepResult returnvalue = new StepResult(stat, r.ToString());

的行动没有问题得手,数字清晰地写入到DataGridView。

the actions succeed with no problem, the numbers are written cleanly to the DataGridView.

我很困惑。我假定这是一个莫名其妙字符串的问题,但任何人都可以想出一个更清楚的解释?

I'm baffled. I'm assuming it's somehow a string literal problem, but can anyone come up with a clearer explanation?

推荐答案

既然你是做UI通过事件订阅绑定的你会发现这是很有帮助的;这是一个例子,我写了前一阵子,显示如何继承的BindingList< T> 这样的通知编组自动UI线程

Since you are doing UI binding via event subscription, you might find this helpful; it is an example I wrote a while ago that shows how to subclass BindingList<T> so that the notifications are marshalled to the UI thread automatically.

如果没有同步上下文(即控制台模式),然后将其恢复到简单的直接调用,所以没有开销。当UI线程运行,注意,这基本上是使用 Control.Invoke ,其本身只是直接运行委托,如果它是在UI线程上。所以只有当数据正在从非UI线程编辑任何开关 - 伸出我们想要;-p

If there is no sync-context (i.e. console mode), then it reverts back to the simple direct invoke, so there is no overhead. When running in UI thread, note that this essentially uses Control.Invoke, which itself just runs the delegate directly if it is on the UI thread. So there is only any switch if the data is being edited from a non-UI thread - juts what we want ;-p

这篇关于奇怪的跨线程UI错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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