2010-10-18 72 views
5

嘿,我的代码序列是这样的:GUI直到代码完成

label.Text = "update 0"; 
doWork(); 
label.Text = "update 1"; 
doWork2(); 
label.Text = "update 2"; 

基本上,GUI不更新可言,直到所有的代码执行完毕。如何克服这一点?

回答

16

一个丑陋的黑客是使用Application.DoEvents。虽然这有效,但我建议不要这样做。

更好的解决方案是使用BackgroundWorker或单独的线程执行长时间运行的任务。不要使用GUI线程,因为这会导致它阻塞。

需要注意的一个重要的事情是,必须在GUI线程上对GUI进行更改,因此您需要将控制权转移回GUI线程以便标记更新。这是通过使用Invoke完成的。如果您使用BackgroundWorker,则可以使用ReportProgress - 它将自动为您处理调用Invoke。

+3

有关[背景工作者类](http:// bit。ly/a9VgVn)和一个[如何使用它的例子](http://bit.ly/ailRTF) – codingbadger 2010-10-18 12:42:08

0

当前,您的所有处理都是在主(UI)线程上执行的,因此必须先完成所有处理,然后UI线程才有空闲周期来重新绘制UI。

你有2种方法克服这一点。不推荐的第一种方法是使用
Application.DoEvents();只要希望处理Windows消息队列,就可以运行它。

其他建议的方法:创建另一个线程来执行处理,并使用委托将UI更新传递回UI线程。如果您是多线程开发的新手,那么可以尝试使用BackgroundWorker。

2

当UI获取WM_PAINT消息来重新绘制屏幕时,UI将更新。如果您正在执行您的代码,则不会执行消息处理例程。

所以你可以做以下操作以启用执行消息处理程序的:

Application.DoEvents,调用消息处理程序,然后返回。这对于大型工作来说并不理想,但对于小型程序而言,它可能是一种更简单的解决方案,而不是引入线程。

0

GUI以这种方式运行代码时无法更新。 Windows上的GUI依赖于消息处理,并且当你处于代码中时消息处理被暂停 - 无论你如何处理标签,按钮等,它们都将在代码退出后更新,并且表单的主要消息循环是处理。

您有几种选择在这里:

  • 移动处理其他线程和面临的invoke()situtations
  • 调用的DoEvents(),并允许GUI你的DoWork之间刷新调用
  • 做的所有工作并稍后更新