C++ 在MFC中处理耗时的操作

C++ 在MFC中处理耗时的操作,c++,winapi,visual-c++,mfc,C++,Winapi,Visual C++,Mfc,我有一个基于MFC的遗留应用程序,到目前为止,我无法在其中进行太多修改 有一个功能涉及从INI文件读取/写入数据。写这篇文章时要记住,ini文件中的设置数量将非常少。但现在它已经变得非常巨大 因此,在执行此任务时,大约需要30分钟 问题是,当用户单击应用程序时,应用程序被锁定,窗口窗口显示它没有响应对话框,询问用户是否需要等待应用程序响应或退出 现在对我来说,我可以安排时间了。但我不希望窗口显示“无响应”行为 我认为问题在于,主线程在这个过程中变得繁忙,UI挂起。我对此不确定,因为我只是在猜测

我有一个基于MFC的遗留应用程序,到目前为止,我无法在其中进行太多修改

有一个功能涉及从INI文件读取/写入数据。写这篇文章时要记住,ini文件中的设置数量将非常少。但现在它已经变得非常巨大

因此,在执行此任务时,大约需要30分钟

问题是,当用户单击应用程序时,应用程序被锁定,窗口窗口显示它没有响应对话框,询问用户是否需要等待应用程序响应或退出

现在对我来说,我可以安排时间了。但我不希望窗口显示“无响应”行为

我认为问题在于,主线程在这个过程中变得繁忙,UI挂起。我对此不确定,因为我只是在猜测

为了处理这个问题,我创建了一个线程并在其中调用这个函数。但是在这个线程函数中,我不能调用
AfxGetMainWnd()函数,因为它返回
NULL

这将是非常有帮助的,如果有人请让我知道,如何处理这种情况(离开理想的情况下不发生这种情况)

此外,欢迎提供任何好的建议

我的另一个想法是将这段代码放在进度条对话框上。---对此的思考是受欢迎的


谢谢

在MFC应用程序中使用线程的诀窍是记住只有主线程才能访问所有GUI元素。因此,如果您剥离一个线程来做一些工作,您需要以某种方式将更新和修改传回主线程,并让它进行GUI更新

最简单的方法是向自己发送消息,消息泵位于主线程上,因此它将始终拾取消息。一旦你知道了,这真的很简单


因此,创建一些WM_用户消息,并在需要时从您的线程发送它们,并按正常方式处理它们。

这里解释了如何将自定义消息从工作线程发送到MFC主线程(请参阅常见问题12):


您应该在工作线程中读取文件。如果您想要一个进度对话框,请将其放在主线程中,并向其发布消息以更新进度显示。

以下是我针对这种情况所做的一个技巧。我主要创建基于对话框的应用程序,用于测试各种电子产品或处理数据等。简单的东西,但有人想做一些UI多任务,只是保持简单。 我增加了这个功能:

void CWhateverApp::doRepaints(void)
    {
        MSG msg;
        while (PeekMessage(&msg,NULL,0,0xFFFFFFFF,PM_REMOVE))
        DispatchMessage(&msg);
    }
在我做任何处理的时候,周期性地调用它。称它为每秒10倍是很好的,但即使每秒一次也能提供良好的UI体验。另外一个技巧是:有一个带有处理程序的“取消”按钮,该处理程序在单击时将bool设置为true。(比如,打电话给bool m_doCancel)。现在,当您开始执行耗时的任务时,请执行以下操作:

m_doCancel= false;
现在执行您的任务,经常调用doRepaints(),调用doRepaint()后检查bool:

if (m_doCancel == true) { /* stop processing */ }
这样,您就可以让用户退出并处理重绘等操作。
FWIW

J

感谢您在MFC中使用线程的技巧。请验证大多数GUI框架是这样工作的,还是MFC的个人信息。@gbjbaanb范围
WM_USER
WM_APP-1
中的消息是为控件实现保留的。永远不要将其用于应用程序内部通信;使用
WM_APP+x
消息,这就是它们的用途@亲爱的,所有针对Windows API的框架都有单线程GUI的限制。虽然并非完全不可能,但使用Windows API实现多线程GUI是非常具有挑战性的。任何单线程GUI都会有相同的限制,主要是因为实现者不会考虑线程问题,因此最好假设在这些情况下,所有操作都发生在UI线程上。故意使用线程的UI是不同的,但它们并不多(毕竟,为什么要麻烦呢?你只有一个人操作GUI,线程只是为了一点点好处而使事情复杂化)。