关于多线程:如何在C#中从UI线程运行代码

How to run code from UI thread in C#

本问题已经有最佳答案,请猛点这里访问。

有没有一种方法可以在UI线程中运行代码,同时在其外部调用它?我知道它基本上需要使用control.Invokecontrol.BeginInvoke。我的问题是我没有访问UI元素来使用这些方法。

我的情况是这样的:

  • UI-DataTable设置为数据源的DataGridView
  • 线程(backgroundworker)写在MainForm UI之外,它更新(添加行)上面提到的数据表
  • 我的应用程序有问题,所以我写了一个简单的应用程序,只包含上面提到的元素,来检查它是如何工作的(或者为什么不工作),我发现:

  • 当我在backgroundWorker线程中更新dataTable时,DataGridView看不到这一点(可能所有事件都是从其他线程激发的),甚至调用dgv.refresh()也不起作用(它更新dgv,但有时dgv会断开,不显示任何内容或只显示一行),只强制dgv通过调整大小、滚动等进行刷新。强制dgv显示来自dat的数据可
  • 当我能够运行invoke时,一切都可以正常工作,无需多说
  • 但这只是一个简单的应用程序,我把所有东西都放在一个文件中。如果我的"其他线程"看不到用户界面代码,我该如何处理更大的应用程序?为了访问该线程,是否必须以某种方式将单个控件作为参数传递?还是有其他更好的解决方案?


    您可以通过以下方式使用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的代码。