2009-11-03 100 views
9

我的應用程序可能需要一段時間才能連接到數據庫。這個連接是通過一個庫函數調用完成的,也就是說,我不能在那裏放置進度更新並進行回調或類似的事情。如何在單獨的線程中使用進度條創建MFC對話框?

我的想法是在連接到數據庫之前,在單獨的線程中創建一個帶有進度條的對話框。此對話框將不斷更改CProgressCtrl::StepIt()的進度狀態,以便用戶看到發生的事情。
之後,對話框設置和做它的事情我想從主線程調用數據庫連接功能。 連接功能完成後,我想停止進度條線程。

讓我畫一幅畫:

CMyApp::  ProgressThread 
InitInstance()  . 
    |    . 
    |    . 
    +-Create Dialog-+ 
    |    | 
    |    Animate 
Connect   Progress 
    to    Bar 
    DB    | 
    |    | 
    +-Destroy Dlg---+ 
    |    . 
    |    . 

這可能嗎?如果是,如何?

也許整個事情也會使用定時器。可能會簡單得多,但我也無法讓它工作。

  1. 我知道CProgressCtrl::SetMarquee()這可能正是我所需要的,但我不能使用它,因爲應用程序沒有Unicode支持。
  2. 我可以將db連接調用移動到一個單獨的線程中,但這樣看起來好像對代碼進行了很多更改並且額外處理了連接錯誤。

更新2
我得到它的工作AlexEzh和哈維爾·佩德羅·德建議的方式:把DB塞入到它自己的線程。
最初我擔心錯誤處理是如何完成的,但實際上它與以前的方式非常相似。

  1. 在主線程中,我使用連接參數,結果標誌和線程運行標誌創建了一個結構。後者最初設置爲true
  2. 我創建一個線程並將該結構作爲參數傳遞。
  3. 我創建一個對話框,在主線程中顯示進度條。
  4. 另外在主線程中有一個循環,它在設置線程運行標誌時運行。它調用CMyDialog::Animate(),它調用CProgressCtrl::StepIt(),然後Sleep()有點。
  5. 線程執行db連接代碼並在完成時將運行標誌設置爲false
  6. 當主線程退出循環時,它可以像以前一樣處理錯誤。

缺點:將鼠標移到窗口上不起作用。它是隱形的。因此不能使用取消按鈕或其他交互式對話元素。不過,我可以忍受這一點。

既然你喜歡的圖,這裏是現在的樣子:

CMyApp::  WorkerThread 
InitInstance()  . 
    |    . 
    |    . 
Create Dialog  . 
    |    . 
    +-Start Thread--+ 
    |    | 
    |    Connect 
Animate   to 
Progress   DB 
    Bar    | 
    |    | 
    +-Thread Ends---+ 
    |    . 
Destroy Dlg  . 
    |    . 
+3

+1爲圖 – 2009-11-03 19:52:12

+0

您可以在ANSI應用程序調用SetMarquee(),但它不會幫你,因爲是動畫進度條的計時器被稱爲主線程也 – 2009-11-03 19:55:25

+0

在我afxcmn上。h看起來像這樣: ** if(_WIN32_WINNT> = 0x0501)&& defined(UNICODE)\ n BOOL SetMarquee(_In_ BOOL fMarqueeMode,_In_ int nInterval); \ n #endif \t // _WIN32_WINNT> = 0x0501 && defined(UNICODE)\ n ** 這就是爲什麼我不能調用它。 – foraidt 2009-11-04 08:46:08

回答

2

將DB連接邏輯移動到單獨的線程仍然更安全。隨着對話線程DB,你就能重繪對話框中的進度條而不是其他控件。

+0

我可以通過調用RedrawWindow()來重繪整個對話框。如果我不這樣做,只有進度條是動畫的。 – foraidt 2009-11-04 15:51:06

7

我希望this一篇關於用進度條創建自己的線程啓動畫面可能會有所幫助。我在解決MFC消息隊列級別的線程鎖定問題的同時寫了它。

2
  1. 使用AfxBeginThread創建工作線程。
  2. 在該線程創建CProgressCtrl並調用Create,通過對話作爲CProgressCtrl的父,使用選框風格的進度控制。
  3. 在線程中創建消息等待循環:

    MSG msg;
    而(的GetMessage(&消息,NULL,0,0))
    {
    的TranslateMessage(& MSG);
    DispatchMessage函數(& MSG);
    }

  4. 消息循環需要檢查全局標誌以查看是否退出循環。

+0

這是行不通的。閱讀我的答案。 – 2009-11-03 20:17:52

+1

@Kirill這適用於我,在我的項目中,究竟是不是假設工作? – 2009-11-03 21:18:32

+0

MFC線程可能在創建函數中死鎖。爲了避免這種情況,你應該使用非MFC線程。 – 2009-11-04 09:45:21

1

您是否嘗試過使用SendMessagePBM_SETMARQUEE,而不是SetMarquee。我從來沒有嘗試過自己,但它應該工作。

在我看來,實現你想要做的最簡單的方法是在UI線程中同時進行ProgressBar和數據庫連接,並使用OnTimer在進度條中調用StepIt。 您還可以創建在UI線程的進度條,並使用自定義消息的工作線程修改的進展狀況。

反正我AlexEzh同意,要做到這一點的最好辦法是使整個非UI工作的工作線程。

+0

當我嘗試過時發送消息沒有效果。 – foraidt 2009-11-04 10:14:22

1

創建一個成員變量如

CProgressCtrl m_progress; 

與進度條ID

添加在DDX_Controlm_progressDoDataExcchange添加下按鈕點擊功能下面的代碼。

m_progress.setRange(0,100); 
m_progress.SetPos(1); 
+0

這只是非常基本的信息,它既沒有被要求,也沒有解決多線程問題。 – foraidt 2014-02-18 07:59:28

相關問題