在Windows窗体中处理时更新标签

问题描述 投票:30回答:6

在处理时更新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..."
}

一些示例代码是什么?

究竟是什么叫做?它是线程还是代理?

winforms label progress
6个回答
59
投票

快速解决方案是:

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

你真的想避免使用DoEvents,否则如果用户反复按下表单上的按钮,你就会遇到问题。


13
投票

您应该在另一个线程上执行此操作,然后从该线程更新UI线程。您通过在UI线程上执行此工作来阻止进一步处理。

如果您无法将此代码移动到UI线程,那么您可以随时调用Application.DoEvents,但我强烈建议您首先探索这些选项:


13
投票

您需要将数据从一个线程转移到另一个线程。这可以通过几种方式完成......

首先,你的“后台”线程可以更新某种“CurrentStatus”字符串变量,它随着它的变化而变化。然后,您可以在表单上放置一个计时器,然后获取CurrentStatus变量并使用它更新标签。

其次,您可以使用标签控件的InvokeRequired属性,使用委托从后台线程调用操作到UI线程。所以例如......

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;
}

您可以从任何线程(UI或后台)调用UpdateStatus()方法,它将检测是否需要在主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
投票

如果您的处理很漫长,请在后台工作线程中进行。

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx


0
投票

我还建议使用:

Application.DoEvents();

处理当前在消息队列中的所有Windows消息。

© www.soinside.com 2019 - 2024. All rights reserved.