【问题标题】:How to run code from UI thread in C# [duplicate]如何在 C# 中从 UI 线程运行代码 [重复]
【发布时间】:2015-02-17 00:11:32
【问题描述】:

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

我的情况是这样的:

  1. UI - 将 DataTable 设置为 DataSource 的 DataGridView
  2. 线程 (BackgroundWorker) 在 MainForm UI 之外编写,用于更新(添加行)上述 DataTable

我的应用出现了问题,所以我编写了一个仅包含上述元素的简单应用,以检查它是如何工作的(或者更确切地说为什么它不工作),我发现:

  1. 当我在我的 BackgroundWorker 线程中更新 DataTable 时,DataGridview 看不到这个(可能所有事件都是从其他线程触发的),即使调用 DGV.Refresh() 也不起作用(它更新 DGV,但有时 DGV 获取损坏,不显示任何内容或仅显示 1 行),仅通过调整大小、滚动等强制 DGV 刷新。强制 DGV 显示来自 DataTable 的数据
  2. 当我能够运行 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


【解决方案1】:

您可以通过以下方式使用 Application.OpenForms:

    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
    }

【讨论】:

  • 像魅力一样工作^_^当然,也许有更好的解决方案,但这就是我现在所需要的,谢谢
【解决方案2】:

您始终可以使用Application.OpenForms[0] 来获取对主窗体的引用,从而可以调用Invoke

我还要说你的方法不是那么聪明。我会在后台工作人员中创建一个新的DataTable 并将其作为后台工作人员的结果返回。

然后,当工作人员完成时(在 UI 线程的上下文中调用 RunWorkerCompleted 事件),我会将结果记录合并到绑定的数据表中。这提供了更新 UI 的代码和甚至可能无头运行的代码的清晰分离。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-05
    • 2012-10-02
    • 2012-05-21
    • 2013-06-16
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多