How to run code from UI thread in C#
有没有一种方法可以在UI线程中运行代码,同时在其外部调用它?我知道它基本上需要使用control.Invoke或control.BeginInvoke。我的问题是我没有访问UI元素来使用这些方法。
我的情况是这样的:
UI-DataTable设置为数据源的DataGridView
线程(backgroundworker)写在MainForm UI之外,它更新(添加行)上面提到的数据表
我的应用程序有问题,所以我写了一个简单的应用程序,只包含上面提到的元素,来检查它是如何工作的(或者为什么不工作),我发现:
当我在backgroundWorker线程中更新dataTable时,DataGridView看不到这一点(可能所有事件都是从其他线程激发的),甚至调用dgv.refresh()也不起作用(它更新dgv,但有时dgv会断开,不显示任何内容或只显示一行),只强制dgv通过调整大小、滚动等进行刷新。强制dgv显示来自dat的数据可
当我能够运行invoke时,一切都可以正常工作,无需多说
但这只是一个简单的应用程序,我把所有东西都放在一个文件中。如果我的"其他线程"看不到用户界面代码,我该如何处理更大的应用程序?为了访问该线程,是否必须以某种方式将单个控件作为参数传递?还是有其他更好的解决方案?
- 型将数据源和控件与UI和BackgroundWorker分离。这样,2个中的任何一个都可以访问一个公共控件。向国际奥委会征求意见。您也可以使用async/await,但是从它的声音来看,您根本没有访问UI代码的权限?你在操纵第三方程序?
- 型使用ReportProgress方法和ProgressChanged事件实际更新您的用户界面如何?它们就是为了这个目的而制造的。例如,请参阅msdn.microsoft.com/en-us/library/…。
- 型这可以帮助您:WinForms多线程数据绑定方案,最佳实践?
- 型我想您正在创建一个新的线程来更新来自UI线程的数据。您应该能够获取回调,然后使用control.begininvoke进行UI更新。如果需要更好的绑定,请使用bindingsource。
您可以通过以下方式使用application.openforms:
1 2 3 4 5 6 7 8 9 10 11 12
| public void DoSomething(string s)
{
var form = System.Windows.Forms.Application.OpenForms[0];
if (form.InvokeRequired)
{
Action<string> m = DoSomething;
form.Invoke(m, s);
return;
}
//do something
} |
- 当然,也许有更好的解决方案,但这是我现在所需要的,谢谢。
您可以使用Application.OpenForms[0]来获取对主窗体的引用,因此可以调用Invoke。
另外,我想说的是,你的方法并不那么聪明。我将在后台工作人员中创建一个新的DataTable,并将其作为后台工作人员的结果返回。
然后,当工作进程完成时(在UI线程的上下文中调用RunWorkerCompleted事件),我将把结果记录合并到绑定的数据表中。这提供了一个清晰的代码分离,更新用户界面和可能运行headless的代码。