MFC 是基于消息队列响应的应用程序框架,UI 和后台关联的代码都属于主工作进程, 如果和UI关联的后台代码阻塞住,那么UI会失去相应,无法接受用户的操作。一般的,如果一段代码需要较长的执行时间,我们会新建一个线程去执行这段代码,执行完后再把结果报告给主工作线程。今天看到一段代码,讲的是DoEvents函数的使用,它可以让出当前操作对系统的占有权,让系统先响应其它消息,然后再回来处理当前任务,摘自MSDN的解释如下:
在运行 Windows 窗体时,它会创建新窗体,然后等待事件来处理。每次窗体处理事件时,它处理与该事件相关联的所有代码。在队列中等待的所有其他事件。虽然您的代码处理事件时,您的应用程序没有响应。例如,如果另一个窗口拖动在最前面,也不重新绘制窗口中。
如果您调用DoEvents在代码中,您的应用程序可以处理其他事件。例如,如果您将数据添加到窗体ListBox并添加DoEvents到代码中,您的窗体可时重新绘制另一个窗口拖到它。如果您删除DoEvents从您的代码,您的窗体不会重新绘制按钮的单击事件处理程序完成之前执行。
通常情况下,您将在处理消息循环中使用此方法。
Note:
调用此方法会导致当前线程在处理所有等待窗口消息时要挂起。如果消息导致事件被触发,可能会执行应用程序代码的其他区域。这会导致您的应用程序展示难以调试的意外的行为。如果您执行的操作或需要很长时间的计算,通常最好是一个新的线程上执行的运算
函数实现如下:
void DoEvents()
{
MSG msg;
while(::PeekMessage(&msg,NULL,0,0,PM_REMOVE));
{
::DispatchMessage(&msg);
::TranslateMessage(&msg);
}
}
示例:
如果后台代码是这样子的:
void myAPP::OnButton1()
{
UINT i = 0;
for(i=0;i<10000;i++)
{
//Nothing;
}
}
那么UI只能等for循环执行完才能响应新的消息,而如果像下面这样:
void myAPP::OnButton1()
{
UINT i = 0;
for(i=0;i<10000;i++)
{
DoEvents();
}
}
在for循环的每一个loop里面,都能再次响应UI的消息。