【问题标题】:Accessing a form's control from a separate thread从单独的线程访问表单的控件
【发布时间】:2011-09-30 11:42:48
【问题描述】:

我正在练习线程并遇到了这个问题。情况是这样的:

  1. 我在一个表单上有 4 个进度条,一个用于下载文件,一个用于显示页面加载状态等...

  2. 我必须从一个单独的线程控制每个 ProgressBar 的进度。

问题是我收到了一个 InvalidOperationException,上面写着

跨线程操作无效:从控制“progressBar1”访问 与创建它的线程不同的线程。

我在这种方法上错了吗,或者有人可以告诉我如何实现吗?

【问题讨论】:

  • 查看 Jon Skeet 关于 Windows 窗体中的线程的 this 文章。它应该把事情弄清楚。简短的解释是您需要从其他线程调用 UI 元素,因为 UI 在其自己的线程上运行。

标签: c# winforms multithreading


【解决方案1】:

Control 只能在创建它的线程(即 UI 线程)中访问。

您必须执行以下操作:

Invoke(new Action(() =>
{
    progressBar1.Value = newValue;
}));

invoke 方法然后在 UI 线程上执行给定的委托。

【讨论】:

    【解决方案2】:

    您可以检查Control.InvokeRequired 标志,然后在必要时使用Control.Invoke 方法。 Control.Invoke 接受一个委托,因此您可以使用内置的 Action

    public void UpdateProgress(int percentComplete)
    {
       if (!InvokeRequired)
       {
          ProgressBar.Value = percentComplete;
       }
       else
       {
          Invoke(new Action<int>(UpdateProgress), percentComplete);
       }
    }
    

    【讨论】:

      【解决方案3】:

      UI 元素只能由 UI 线程访问。 WinForms 和 WPF/Silverlight 不允许从多个线程访问控件。

      A work-around to this limitation can be found here.

      【讨论】:

        【解决方案4】:
         private void Form1_Load(object sender, EventArgs e)
            {
                CheckForIllegalCrossThreadCalls = false;
            }
        

        也许这会奏效。

        【讨论】:

        • 这将阻止错误出现,但实际上并不能解决问题。此线程中已经有其他更好的答案可以实际解决问题并有助于更好地理解它首先发生的原因。
        • 我也喜欢危险的生活,这对我的一个用例很有效。谢谢。
        【解决方案5】:

        您需要从非 UI 线程调用方法 Invoke 以对表单和其他控件执行一些操作。

        【讨论】:

        • 我不是高级程序员。您能否就我们如何做到这一点提出建议?谢谢
        • @Chandu-Indyaah - 如果你不是高级程序员,那么你应该使用 BackgroundWorker。
        猜你喜欢
        • 2019-05-30
        • 1970-01-01
        • 2011-01-27
        • 2016-02-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-14
        • 2016-08-24
        相关资源
        最近更新 更多