基于Dialog的MFC应用程序的应用程序范围的定期任务

时间:2010-01-29 04:00:05

标签: c++ winapi windows-mobile mfc native

在单文档界面(SDI)或多文档界面(MDI)MFC应用程序中,我在View中创建了一个应用程序范围的计时器。只要应用程序正在运行,计时器就会打勾并触发一些定期操作。

如何使用基于Dialog的MFC应用程序执行相同的操作?

  1. 我应该创建Thread的Timer(SetTimer with NULL HWND)并将回调函数传递给它吗?
  2. 我应该创建工作线程吗?我对其他项目的体验是当我尝试从非GUI /工作线程显示一些反馈GUI时,我需要推出自己的“委托”/命令模式和“委托调用者”/命令调用程序。工作线程将向UI线程发送消息(我认为使用消息比跨线程边界,CMIIW处理时的直接函数调用更安全)。 UI线程将是“委托”/命令调用者。如果不这样做并确保窗口/对话框具有正确的父级将导致诸如应用程序之类的混淆行为突然消失在后台;窗口/对话框显示在当前窗口/对话框后面,导致当前窗口无响应/不可点击。可能我做错了,但在处理线程时遇到了很多问题。
  3. 是否有最佳做法?

4 个答案:

答案 0 :(得分:1)

计时器在基于对话框的应用程序中也可用作SDI或MDI应用程序。 OTOH,定时器(大多数)是16位Windows的剩余部分。如果你想定期做事,工作线程通常是更好的方法(是的,Windows Mobile支持多线程)。

编辑:在基于对话框的应用程序中,主对话框(基本上)存在于应用程序的整个生命周期中。除非您在应用程序启动和对话框创建或对话框销毁和应用程序退出之间的毫秒内确实需要计时器,否则只需将其附加到对话框即可。否则,您可以将它附加到主窗口 - MFC创建和销毁,即使它从未显示过。

答案 1 :(得分:0)

如果使用MFC向导创建基于对话框的应用程序,则可能有隐藏的视图窗口和对话窗口。视图窗口使用DoModal()创建对话框,该对话框在同一个线程中运行对话框,有效地暂停视图窗口。

对话框打开时,视图窗口不会处理任何事件。因此,如果视图窗口拥有计时器,它将不会处理计时器事件。

最简单的解决方案是在对话框中创建计时器,让对话框处理计时器消息。

答案 2 :(得分:0)

IMO,如果它解决了问题,请使用Timer。正如您所提到的,在MFC中与UI交互的工作线程可能比它的价值更麻烦。

如果问题很简单,定时器就足够了,那就是我用的东西(记住KISS)

SetTimer不需要交给窗口工作,它可以调用回调方法。

您可以在您的应用程序中使用它 - 在您的CWinApp(或任何地方)声明

static void CALLBACK OnTimer(HWND, UINT, UINT, DWORD);

然后在InitInstance来电SetTimer(0, [eventid], [time period], OnTimer);

OnTimer中,您可以通过AfxGetApp()theApp返回CWinApp实例,因为只有一个。

答案 3 :(得分:0)

第二次尝试: 我之前的回答是匆匆而且不正确。

您的基本vanilla MFC Dialog应用程序仅使用一个线程。主线程从一个派生自CWinApp的类开始。在InitInstance()方法中,它使用CDialog :: DoModal()启动对话框。在对话框关闭之前,此功能不会返回。

当对话框正在运行时,CWinApp类不处理任何消息,因此不会看到WM_TIMER。

有很多方法可以解决这个问题。

  1. 让第一个对话框拥有计时器并使所有其他对话框成为子对象。这可能没问题,具体取决于您的对话要求,但可能限制太多。

  2. 将第一个Dialog作为无模式启动,即使用Create()而不是DoModal()。 Create()立即返回(将Dialog放入另一个线程)。然后,您可以在CWinApp类中创建消息循环并在那里处理计时器。由于CWinApp类没有窗口,因此您必须使用线程计时器而不是窗口计时器。 (或者如果更方便的话,你可以创建一个隐藏的窗口。)

  3. 您可以破解对话框的消息循环并使消息传递给CWinApp类的消息处理程序。这非常复杂,不适合胆小的人。

  4. 您可以创建专用的计时器线程。您可能在创建对话框之前从CWinApp类中执行此操作,但其他策略也是可行的。

  5. 这些方案中的任何一个听起来都符合您的需求吗?如果没有,也许你可以更充分地解释你的需求,我们也许能够找到合适的东西。