2013-05-08 35 views
0

我有一个线程与主窗体(UI)并行运行。它所做的(现在)是每秒增加一个计数器。我想在Windows窗体中使用标签显示计数器的值。那可能吗? 当我尝试下面的代码时,ShowValue方法中出现编译错误。我必须声明ShowValue“static”,以便我可以从后台线程调用它。但如果我这样做,我不能使用“这个”。访问ShowValue Form1中的标签。 这是正确的方法吗? 任何提示将不胜感激,谢谢!如何从C#中的后台线程刷新Windows窗体中的标签?

private void count_secs() 
    { 
     while (!stopThread) 
     { 
      if (stopThread) 
      { 
       break; 
      } 
      num2++;      // increment counter 
      Form1.ShowValue(num2);  // display the counter value in the main Form 
      try 
      { 
       Thread.Sleep(1000);  // wait 1 sec. 
      } 
      catch (ThreadInterruptedException) 
      { 
       if (stopThread) 
       { 
        break; 
       } 
      } 
     } 
    } 

然后在我的Form1类中,我有:

public static void ShowValue(int num) 
    { 
     this.label7.Text = num.ToString();  
     // compiler error here: "Keyword 'this' is not valid in a static method. 

    } 

回答

1

不能在静态方法是指一个局部变量(this.label7ShowValue(int num)

你的方法应该是这样的:

public void ShowValue(int num) 
    { 

     if(label7.InvokeREquired) 
     { 
      Action a =() => ShowValue(num); 
      label7.Invoke(a); 
     } 
     else 
     this.label7.Text = num.ToString();  

    } 

在此代码中,将静态调用替换为您的窗体机智h的实例:

private void count_secs() 
    { 
     var frm = new Form1(); //create instance 
     frm.Show(); // show form 

     while (!stopThread) 
     { 
      if (stopThread) 
      { 
       break; 
      } 
      num2++;      // increment counter 

      //use form instance 
      frm.ShowValue(num2);  // display the counter value in the main Form 
      try 
      { 
       Thread.Sleep(1000);  // wait 1 sec. 
      } 
      catch (ThreadInterruptedException) 
      { 
       if (stopThread) 
       { 
        break; 
       } 
      } 
     } 

编辑

您可能要decalre外面方法的形式实例count_secs()

0

两个问题:

  1. 不能使用从该this参考静态上下文。
  2. 您无法从后台线程更新您的用户界面。

解决方案:

  1. 标记方法ShowValue作为实例方法
  2. 使用后台工作或阅读this question这也解释得很好
(即摆脱 static的。)
1

您不能从不同的线程中随机访问GUI元素。您的问题的简短答案是:使用现有的结构。

  • 如果您只是想经常做事,请使用Timer。当时间到了,它会通知你的主线程(“拥有”GUI),你可以在那里更新GUI元素。
  • 如果你真的想创建自己的线程,请使用Backgroundworker。它将提供线程安全的events,您可以从中更新GUI元素。
1

你的第一个问题是让表单实例,如果没有您的通话形式Form实例,那么你会Application.OpenForms属性,如:

Form1 frm = Application.OpenForms["Form1"] as Form1; 
if(frm != null) 
    frm.ShowValue(num2); 

你的第二个问题是,你需要修改方法为实例方法,并把它从十字保存线程例外修改它想:

public void ShowValue(int num) 
{ 
    if (label7.InvokeRequired) 
    { 
     label7.BeginInvoke((MethodInvoker)delegate { label7.Text = num.ToString(); }); 
    } 
    else 
    { 
     label7.Text = num.ToString(); 
    } 
} 
+1

很好的回答,使用'BeginInvoke'就是这样做的方法。 – Jeremy 2013-05-08 07:34:03

0

这不是强制性的,以使ShowValue功能静态的。将其保持为非静态,并用以下代码替换逻辑行Form1.ShowValue(num2)

if (label1.InvokeRequired) 
     label1.BeginInvoke(new Action(() => ShowValue(num2))); 
else 
     label1.Invoke(new Action(() => ShowValue(num2))); 
+0

如果不需要,你为什么要调用标签? – 2013-05-08 08:03:29

+0

不需要。但至少民间人士将能够开始寻找为什么我使用BeginInvoke或Invoke或InvokeRequired的方向,这最终导致他更多的阅读。 – Nair 2013-05-08 08:08:49

+0

我明白了。但两者之间的[差异](http://stackoverflow.com/questions/229554/whats-the-difference-between-invoke-and-begininvoke)是sync或async invoke。但如果不需要调用,则它们不相关。 – 2013-05-08 08:11:14