2009-02-20 20 views
26

在處理時更新Windows窗體應用程序上的標籤的最佳方式是什麼?在Windows窗體中處理時更新標籤

我有一個循環,進行一些處理的文件在用戶的系統上,當用戶點擊一個按鈕。

foreach (System.IO.FileInfo f in dir.GetFiles("*.txt")) 
{ 
    // Do processing 
    // Show progress bar 
    // Update Label on Form, "f.Name is done processing, now processing..." 
} 

什麼是一些示例代碼?

這究竟是什麼?它是線程還是代表?

回答

48

速戰速決你會:

Label1.Text = f.Name + " is done processing, now processing..."; 
Label1.Refresh(); 

你真的想避免DoEvents,否則會出現問題,如果你的用戶重複按表單上的按鈕。

13

應該被另一個線程這樣做,然後再從該線程更新UI線程。您將在UI線程上執行此項工作來阻止進一步的處理。

如果無法移動這個代碼到UI線程,那麼你可以隨時撥打Application.DoEvents,但我強烈建議您首先探究這些選項:

+1

我同意這一點 - 尤其是對於BackgroundWorker。我經常使用它自己。BackgroundWorkers像這樣簡單和容易地進行多線程操作! – Keithius 2009-02-21 16:45:27

13

你需要從一個線程到另一個讓您的數據。這可以通過兩種方式來完成...

首先,你的「後臺」線程可以更新某種「CurrentStatus」字符串變量,它的變化,因爲它去一起。然後,您可以在窗體上放置一個計時器,然後獲取CurrentStatus變量並用它更新標籤。

其次,你可以簡單地調用從後臺線程運行到UI線程使用標籤控件的InvokeRequired屬性的委託。因此,例如...

private delegate void UpdateStatusDelegate(string status); 
private void UpdateStatus(string status) 
{ 
    if (this.label1.InvokeRequired) 
    { 
     this.Invoke(new UpdateStatusDelegate(this.UpdateStatus), new object[] { status }); 
     return; 
    } 

    this.label1.Text = status; 
} 

您可以調用UpdateStatus()從任何線程(UI或背景)方法,它會檢測是否需要調用主UI線程上的操作(和如果是這樣的話)。

實際設置線程,你可以這樣做是這樣的:

private void StartProcessing() 
    { 
     System.Threading.Thread procThread = new System.Threading.Thread(this.Process); 

     procThread.Start(); 
    } 

    private void Process() // This is the actual method of the thread 
    { 
     foreach (System.IO.FileInfo f in dir.GetFiles("*.txt")) 
     { 
      // Do processing 
      // Show progress bar 
      // Update Label on Form, "f.Name is done processing, now processing..." 
      UpdateStatus("Processing " + f.Name + "...");     
     } 
    } 

然後,當用戶點擊「GO」按鈕,你會簡單地調用StartProcessing()。

+1

它必須是完美的答案。 – 2016-12-29 12:44:54