2010-01-29 83 views
3

在单文档界面(SDI)或多文档界面(MDI)MFC应用程序中,我在视图中创建了一个应用程序范围的定时器。只要应用程序正在运行并且触发一些定期操作,计时器就会打勾。使用基于Dialog的MFC应用程序应用宽周期性任务

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

  1. 我应该创建线程的定时器(SetTimer与NULL HWND)并传递回调函数吗?
  2. 我应该创建工作线程吗?我对其他项目的经验是当我尝试从非GUI /工作线程显示一些反馈GUI时,我需要推出自己的“委托”/命令模式和“委托调用者”/命令调用器。工作线程将发送消息(我认为在跨线程边界CMIIW处理消息比直接函数调用安全)到UI线程。而UI线程将成为“委托”/命令调用者。如果没有做到这一点,并确保窗口/对话框有正确的父母会导致bizzare行为,如应用程序突然消失在后台;窗口/对话框显示在当前窗口/对话框的后面,导致当前窗口无响应/不可点击。可能我做错了什么,但是在处理线程时遇到了很多问题。

是否有最佳做法呢?

回答

1

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

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

+0

我知道计时器在基于对话框工作,但我应该把它放在哪里?如果我把它放在对话框中,当对话框被销毁时它会被杀死。我是否应该保持1个对话框始终打开,作为定时器的利基? – 2010-01-29 06:18:43

0

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

当对话框打开时,视图窗口将不处理任何事件。所以,如果视窗拥有定时器,它将不会处理定时器事件。

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

+0

我会在对话框中创建我的定时器,如果我只需要特定的对话框。但我需要定时器在应用程序范围内运行,并且只要应用程序运行就打勾。 – 2010-01-29 06:45:14

+0

我不确定在基于对话框的应用程序中是否存在隐藏的视图,但对话框是在从CWinApp派生的类的InitInstance()期间创建的。在这个函数中,应用程序的主窗口被设置为对话框(而不是SDI/MDI应用程序中的框架),所以我觉得对话框是我从MFC向导中获得的唯一HWND。 – 2010-01-29 06:50:38

+0

@afriza - 你是对的,MFC向导将对话框定义为主窗口,并且没有由它创建的隐藏视图。 – Ruddy 2010-01-29 11:30:08

0

IMO,使用定时器,如果它解决了问题。正如你所提到的,一个工作线程与用户界面进行交互,在MFC中,有时可能比它的价值更麻烦。

如果问题是很简单的定时器足够了,那是什么我会使用(记住KISS)

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

您可以使用您的应用程序 - 宣布在你的CWinApp(或任何地方真的)

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

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

OnTimer,您可以通过AfxGetApp()我们回到CWinApp的实例或theApp,因为只有一个。

+0

我认为[eventid]将被忽略,因为你正在创建线程的定时器而不是HWND定时器。 – 2010-02-01 04:26:18

0

第二次尝试:我以前的回答很匆忙,而且不正确。

您的基本香草MFC对话框应用程序只使用一个线程。主线程从CWinApp派生的类开始。在InitInstance()方法中,它使用CDialog :: DoModal()启动对话框。直到对话框关闭,此功能才会返回。

对话框运行时,CWinApp类不处理任何消息,所以不会看到WM_TIMER。

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

  1. 让第一个对话框拥有计时器并使其它所有对话框成为子对象。这可能是好的,这取决于您的对话要求,但可能过于严格。

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

  3. 你可以破解对话框的消息循环,并将消息传递给CWinApp类的消息处理程序。这是相当复杂的,而不是为了那些胆小的人。

  4. 您可以创建一个专用的计时器线程。在创建对话框之前,你可能会从CWinApp类中做到这一点,但其他策略是可能的。

是否有任何这些方案听起来像他们适合您的需求?如果没有,也许你可以更全面地解释你的需求,我们可能会提出一些合适的建议。

+0

Create()立即返回(将对话框放入不同的线程)。 “它感觉不对。直接返回并不意味着它会创建一个新线程。它只能依靠主消息循环将消息泵送到对话框。顺便说一句,我目前正在与我的应用程序的非周期性部分冲。希望当我到达那里时,我会更新这个'线程'。感谢您关注此“线索” – 2010-02-02 14:38:28

相关问题