21

我使用另一个类中的线程编写来更新标签。标签是 Winform Main 类中的内容。

 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();

你怎么看,我将标签的引用传递给第二类的构造函数。在第二个类(扫描仪)中,我有一个名为“自动扫描仪”的方法,它应该使用以下代码更新标签:

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();        
}

我在更新标签时收到此错误:

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

我将 .net 4 与 Winform C# 一起使用。

非常感谢您的回答。

新闻:问题是这一行:

trd.Join();

此行阻止了我的 GUI,并且标签未更新。有什么方法可以控制线程的结束并更新标签直到结束?谢谢

4

3 回答 3

52

您不能从 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

于 2013-02-15T07:56:10.027 回答
11

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

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

 this.Invoke(inv);
}

您收到错误是因为您的 UI 线程持有标签,并且由于您尝试通过另一个线程更新它,您会遇到跨线程异常。

您可能还会看到:Windows 窗体中的线程

于 2013-02-15T07:55:02.487 回答
3

只需使用Control.Invoke 方法Control.BeginInvoke 方法

很好的例子:如何:对 Windows 窗体控件进行线程安全调用

于 2013-02-15T07:55:59.563 回答