从另一个线程更新标签

21

我在另一个类中使用线程编写以更新一个标签。该标签是Winform主类中的内容。

 Scanner scanner = new Scanner(ref lblCont);
 scanner.ListaFile = this.listFiles;
 Thread trd = new Thread(new ThreadStart(scanner.automaticScanner));
 trd.IsBackground = true;
 trd.Start();
 while (!trd.IsAlive) ;
 trd.Join();

如您所见,我将标签的引用传递给第二个类的构造函数。 在第二个类(Scanner)中,我有一个名为“automaticScanner”的方法,该方法应使用以下代码更新标签:

public Scanner(ref ToolStripStatusLabel _lblContatore)
{
        lblCounter= _lblContatore;
}
Thread threadUpdateCounter = new Thread(new ThreadStart(this.UpdateCounter));
threadUpdateCounter.IsBackground = true;
threadUpdateCounter.Start();
while (!threadUpdateCounter .IsAlive) ;
threadUpdateCounter.Join();

private void AggiornaContatore()
{
  this.lblCounter.Text = this.index.ToString();        
}

我在更新标签时收到了这个错误:

跨线程操作无效:从创建它的线程以外的线程访问控件“Main”

我使用的是 .net 4 和 Winform C#。

非常感谢答案。

消息:

trd.Join();

这行代码阻塞了我的GUI,标签没有更新。 有方法控制线程的完成并在结束之前更新标签吗? 谢谢


但是...这种方式调用线程正确吗? Thread trd = new Thread(new ThreadStart(scanner.scansioneAutomatica)); trd.IsBackground = true; trd.Start(); while (!trd.IsAlive) ; trd.Join(); 以这种方式,GUI被阻塞了!:S - Antonio
在类中包含代码 Action y; 和处理计时器已过去事件的函数 private void T_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { c++; //委托表达式为 "y = () => label1.Text = c.ToString()" label1.Invoke(y = () => label1.Text = c.ToString());
}
- Antonio Leite
3个回答

54

您不能在除 UI 线程以外的其他线程中更新 UI。请使用此代码在 UI 线程上更新线程。

 private void AggiornaContatore()
 {         
     if(this.lblCounter.InvokeRequired)
     {
         this.lblCounter.BeginInvoke((MethodInvoker) delegate() {this.lblCounter.Text = this.index.ToString(); ;});    
     }
     else
     {
         this.lblCounter.Text = this.index.ToString(); ;
     }
 }
请阅读本章以及更多有关线程的内容,以便获得更清晰的了解: http://www.albahari.com/threading/part2.aspx#_Rich_Client_Applications

lblCounter没有包含InvokeRequired的定义,BeginInvoke也是一样。 - Antonio
当我执行这段代码时,标签没有改变... - Antonio
它应该被设置为this.index.ToString()的值。请提供更多的代码以便我们帮助您。 - Igoy
@Yogendra 我已经使用了后台工作器!非常感谢你!现在一切都运作正常! - Antonio
工作得很好,太棒了! - Dracarys
显示剩余5条评论

11

使用MethodInvoker在其他线程中更新标签文本。

private void AggiornaContatore()
{
    MethodInvoker inv = delegate 
    {
      this.lblCounter.Text = this.index.ToString(); 
    }

 this.Invoke(inv);
}

您之所以会出现错误,是因为您的UI线程正在持有该标签,并且由于您正试图通过另一个线程更新它,因此出现了跨线程异常。

您还可以参考:Windows Forms中的线程


我的类不是接口IDisposable,因此找不到this.IsDisposed。 - Antonio
@Antonio,移除检查并直接调用它。 - Habib
在我的类Scanner的方法Aggiorna contatore中找不到方法Invoke。 - Antonio

3

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