在处理时更新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..."
}
一些示例代码是什么?
究竟是什么叫做?它是线程还是代理?
快速解决方案是:
Label1.Text = f.Name + " is done processing, now processing...";
Label1.Refresh();
你真的想避免使用DoEvents
,否则如果用户反复按下表单上的按钮,你就会遇到问题。
您应该在另一个线程上执行此操作,然后从该线程更新UI线程。您通过在UI线程上执行此工作来阻止进一步处理。
如果您无法将此代码移动到UI线程,那么您可以随时调用Application.DoEvents
,但我强烈建议您首先探索这些选项:
您需要将数据从一个线程转移到另一个线程。这可以通过几种方式完成......
首先,你的“后台”线程可以更新某种“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()。
如果您的处理很漫长,请在后台工作线程中进行。
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
我还建议使用:
Application.DoEvents();
处理当前在消息队列中的所有Windows消息。