2013-05-08 41 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