2009-02-20 21 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