2012-07-11 63 views
2

对于我正在处理的项目,我使用一组DataGridView组件来显示一些数据。每个DataGridView都有自己的DataTable关联它。要显示的数据是定期发送的。我的应用程序必须读取这些数据,解析它并相应地填充数据网格。因为我想维护表单的响应能力,所以我在无尽的后台工作人员中实现了数据接收(阻塞)。从线程更新数据绑定数据表安全吗?

在后台worker中,我获取数据并将其解析/转换为适合DataTable的值。现在这是我的问题:目前我将这些值直接分配给DataTable对象。 (所以我从背景工作者的DoWork事件中这样做)

我想知道这是否有效。我确实有索引超出界限例外,我想知道这是否与此有关。这是一个安全和推荐的方式,或者我应该在我的BackgroundWorker的DoWork事件中使用调用来更新DataTables?

+0

为什么你会用这个单线程?看起来你应该为每个控件使用一个Background Worker。你应该做Invokes,不完全确定你在做什么,如果你想要更详细的回复,请提供代码。 – 2012-07-11 14:40:56

回答

3

不,.NET WinForm控件的所有属性(这是假设)影响控件渲染的影响(包括绑定到影响渲染的控件的值)必须在创建控件的线程上进行。

也就是说,有很多时候你会逃避能够做出改变,但行为是不可预知的,不推荐。

在您的具体情况,我建议具有处理线程的工作方式,然后元帅DataTable是复制到UI线程副本(通过调用ISynchronizeInvoke interface实现的一个,其Control class工具)并更新UI线程中的网格。

基本上,您会执行网格绑定的DataTable的更新,并使用从后台线程封送的副本。

+0

我不熟悉WinForms ...但在WPF中,有一个可以在UI线程中运行代码的调度程序。这不可能与WinForms?把这个调度程序调用的委托中的所有数据更新放进去? – Kek 2012-07-11 14:42:36

+0

@kek是的,你可以做到这一点,但你最终做的是调用后台线程,然后调用UI线程,然后执行*工作。重点在于,在后台线程完成所有繁重工作后,您必须将后台线程的数据编组到UI线程(无论是通过调用Windows窗体中的Invoke还是WPF中的Dispatcher)。 – casperOne 2012-07-11 14:44:30

+0

好的......术语编组对我来说不是很清楚......但是,您必须首先处理数据副本并将其复制到。谢谢澄清...... +1回答的完整性 – Kek 2012-07-11 14:49:39

0

那么,没有。 尽管在后台线程中进行计算是一个非常好的主意,但UI更新应始终在UI线程中完成。

当绑定的DataTable到UI元素,你“给”对这些对象的所有权到UI线程在后台线程不再对其进行更新

+0

虽然我不直接从线程更新UI,但只绑定到UI组件的结构。所以如果我理解正确,这并不重要,它应该仍然在UI线程中完成? – 2012-07-11 14:41:35

+0

@WilliamW更新结构将导致连锁反应,导致在UI线程中重新呈现控件。这不应该做。您必须拥有该结构的副本,执行工作,然后将数据封送到主线程,并更新绑定到UI组件的结构。 – casperOne 2012-07-11 14:47:33

+0

编辑答案。 – Kek 2012-07-11 14:50:06

0

公平地说,你不应该更新任何UI从绑定元素一个非ui线程。 虽然很多时候你可能没有看到任何异常,但如果你这样做,它从来没有好的做法,往往会导致异常或更糟糕的是,看不见的错误