2010-01-29 82 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

相關問題