【发布时间】:2015-02-17 00:11:32
【问题描述】:
有没有办法在 UI 线程中运行代码,同时在它之外调用它?我知道它基本上需要使用control.Invoke 或control.BeginInvoke。我的问题是我无法访问 UI 元素来使用这些方法。
我的情况是这样的:
- UI - 将 DataTable 设置为 DataSource 的 DataGridView
- 线程 (BackgroundWorker) 在 MainForm UI 之外编写,用于更新(添加行)上述 DataTable
我的应用出现了问题,所以我编写了一个仅包含上述元素的简单应用,以检查它是如何工作的(或者更确切地说为什么它不工作),我发现:
- 当我在我的 BackgroundWorker 线程中更新 DataTable 时,DataGridview 看不到这个(可能所有事件都是从其他线程触发的),即使调用 DGV.Refresh() 也不起作用(它更新 DGV,但有时 DGV 获取损坏,不显示任何内容或仅显示 1 行),仅通过调整大小、滚动等强制 DGV 刷新。强制 DGV 显示来自 DataTable 的数据
- 当我能够运行 Invoke 时,一切正常,没什么好说的
但这只是一个简单的应用程序,我将所有内容都放在一个文件中。在我的“其他线程”看不到 UI 代码的情况下,我可以用更大的应用程序做什么?我是否必须以某种方式将单个控件作为参数传递,才能访问该线程?还是有其他更好看的解决方案?
【问题讨论】:
-
将数据源和控件与 UI 和 BackgroundWorker 分开。这样,两者中的任何一个都可以访问公共控件。向 IoC 寻求想法。您也可以使用 async/await,但是从它的声音来看,您根本无法访问 UI 代码?所以你在操纵一个第 3 方程序?
-
如何使用
ReportProgress方法和ProgressChanged事件来实际更新您的UI?它们正是为此目的而制造的。有关示例,请参见 msdn.microsoft.com/en-us/library/…。 -
我猜你正在创建一个新线程来从 UI 线程更新数据。您应该能够获取回调,然后使用 control.BeginInvoke 进行 UI 更新。如果您需要更好的绑定,请使用 BindingSource。
标签: c# multithreading winforms