从单独的线程访问窗体控件

20

我正在学习多线程编程,遇到了这个问题。具体情况如下:

  1. 我在一个窗体上有4个进度条,其中一个用于下载文件,一个用于显示页面加载状态等等……

  2. 我需要从不同的线程中控制每个进度条的进度。

问题是我得到了一个InvalidOperationException错误,提示:

跨线程操作无效:尝试访问'progressBar1'控件,它被创建在其他线程中。

我的做法是否有误,还是有人能告诉我如何实现这个功能呢?


2
看看Jon Skeet关于Windows Forms中线程的这篇文章吧,它应该能解决你的问题。简单来说,你需要从其他线程调用UI元素,因为UI运行在自己的线程上。 - alex
5个回答

60

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

你需要做如下操作:

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

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


17

您可以检查Control.InvokeRequired标志,如果需要,可以使用Control.Invoke方法。Control.Invoke需要委托,因此您可以使用内置的Action<T>。

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

12

11
 private void Form1_Load(object sender, EventArgs e)
    {
        CheckForIllegalCrossThreadCalls = false;
    }

也许这会起作用。


6
这将停止错误的出现,但实际上并没有解决问题。此线程中已有其他更好的答案,可以真正解决该问题,并有助于更好地理解为什么首先会发生这种情况。 - Taegost
我也喜欢冒险,而且这对我的一个使用案例很有效。谢谢。 - caliche2000

2
您需要从非UI线程调用Invoke方法才能在窗体和其他控件上执行一些操作。

1
我不是高级程序员。你能告诉我我们该怎么做吗?谢谢。 - Chandra Eskay
如果您不是高级程序员,则应使用BackgroundWorker。 - @Chandu-Indyaah - Security Hound

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接