在处理时更新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
,但我强烈建议您首先探索这些选项:
System.ComponentModel.BackgroundWorker
System.Threading.ThreadPool
System.Threading.Thread
System.Threading.Tasks
命名空间
您需要将数据从一个线程转移到另一个线程.这可以通过几种方式完成......
首先,你的"后台"线程可以更新某种"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().