2009-07-14 48 views
14

我傾向於在大多數應用程序的底部使用StatusStrip進行簡單的狀態更新,偶爾還會使用進度條。如何對ToolStripStatusLabel進行跨線程調用?

但是,它似乎ToolStripStatusLabels不從控件繼承,所以它們沒有.Invoke或.InvokeRequired。那麼,我將如何線程安全地撥打電話來更改它的文本屬性?

爲後人編碼的答案和其他人前來尋找:

Action<string> test=(text) => 
      { 
       if (this._statusStrip.InvokeRequired) this._statusStrip.Invoke(
       new MethodInvoker(() => this._lblStatus.Text = text)); 
       else this._lblStatus.Text = text; 
      }; 

private void TestInvoker(string text) 
    { 
     if (this._statusStrip.InvokeRequired) 
      this._statusStrip.Invoke(
        new MethodInvoker(() => this._lblStatus.Text = text)); 
     else this._lblStatus.Text = text; 
    } 
+0

@Maslow:在周圍Control.Invoke你的邏輯小心。如果不仔細閱讀,文檔中規定的規則是微妙的,容易出錯。請檢查我在答案中的鏈接中的代碼,以便更妥善保護使用Invoke。例如,你的實現不驗證'ToolStrip`沒有被處理,也沒有驗證'ToolStrip`的句柄已經被創建。 – 2009-07-15 01:29:11

+0

除了尚未創建的句柄之外,看起來這些情況除了拋出異常(如果它們出現的話)之外什麼也不做,對吧?如果句柄還沒有創建,我不確定假裝什麼都沒有發生,並且不會拋出異常是有用的。 – Maslow 2009-07-15 12:57:12

回答

27

這是一個很好的問題!

雖然ToolStripStatusLabel不從控件繼承,但包含ToolStrip!使用包含ToolStrip的調用對ToolStripStatusLabel進行調用。

這是因爲ToolStrip手動處理其組件位的繪製,這與WPF管理其組件位的圖形非常相似,不會爲每個組件位生成單獨的句柄。這是有用的,因爲它很容易忘記,每一個Control具有關聯HANDLE和系統只有有限數量的那些拋出,如:

(我之前也已經運行到這一點。我在提到它在another question側邊欄,例如,我應該更新的文本,以反映我最近的理解。)

+1

是的,你甚至可以使用在同一個線程上創建的Forms Invoke方法。但我會選擇Greg D的解決方案,因爲它更符合邏輯。 – 2009-07-14 20:59:18

2

而且,在一般情況下,你不使用InvokeRequired和BeginInvoke的確切同一控制你在代碼中操作,只要你可以保證你正在操作的控件是在同一個線程上創建的(例如,在表單的初始化離子例程),作爲您調用InvokeRequired/BeginInvoke的UI元素。

0

您可以通過使用delegate關鍵字和Control.Invoke()方法來執行此操作。此示例顯示如何管理線程安全。文本.ForeColor調整。

private delegate void SetToolStripDelegate(string text, Color color); 

private void SetToolStrip(string text, Color color) 
{ 
    statusBar.Text = text; 
    statusBar.ForeColor = color; 
} 

裏面的線程上下文可以讓這個方法的這樣一個線程安全的呼叫:

{ // thread begin... 

    // somewhere inside the thread 
    Invoke(new SetToolStripDelegate(SetToolStrip), "Connected.", Color.Green); 

} // thread end... 
0

簡單地說,在經過StatusStrip中的項目,通過StatusStrip也在參數中使用,並用作StatusStrip.BeginInvoke或Invoke方法,並將狀態條項放置在其中。

下面的代碼應該可以幫助您如何調用和更新StatusStrip不僅來自其他任務/線程,而且還來自其他類。

//Coded by Chandraprakash [2017-07-18] 
//frozenprakash.com 

using System; 
using System.Threading; 
using System.Threading.Tasks; 
using System.Windows.Forms; 

namespace UIUpdateFromOtherClass 
{ 

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private void button1_Click(object sender, EventArgs e) 
    { 
     FN_Execute(); 
    } 

    async void FN_Execute() 
    { 
     Second s = new Second(); 
     await Task.Run(() => s.Execute(lbl1, 
             pb1, 
             ss1, 
             ss1Lbl1, 
             ss1Pb1) 
         ); 
     MessageBox.Show("End"); 
    } 

} 

public class Second 
{ 
    public void Execute(Label lbl1, 
         ProgressBar pb1, 

         StatusStrip ss1, 
         ToolStripLabel tsLbl1, 
         ToolStripProgressBar tsPb1) 
    { 
     lbl1.BeginInvoke(new Action(() => 
      lbl1.Text = "Second" 
     )); 

     pb1.BeginInvoke(new Action(() => 
     { 
      pb1.Style = ProgressBarStyle.Marquee; 
      pb1.MarqueeAnimationSpeed = 10; 
     })); 

     ss1.BeginInvoke(new Action(() => 
     { 
      tsLbl1.Text = "Second"; 

      tsPb1.Style = ProgressBarStyle.Marquee; 
      tsPb1.MarqueeAnimationSpeed = 10; 
     })); 

     Thread.Sleep(3000); 
    } 
} 

} 

Windows Forms Screenshot