• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            面對現(xiàn)實,超越自己
            逆水行舟,不進則退
            posts - 269,comments - 32,trackbacks - 0
            1、主程序
             1 m_bStopMsg = TRUE;
             2         HANDLE hPromptThread = StartPromptThread();
             3         if (!hPromptThread)
             4         {
             5             LOG("啟動導(dǎo)入數(shù)據(jù)提示框線程失敗");
             6         }
             7 
             8         while (m_bStopMsg)
             9         {
            10             MSG msg;
            11             ::GetMessage( &msg, this->m_hWnd, NULL, NULL );
            12             ::TranslateMessage( &msg );
            13             ::DispatchMessage( &msg );
            14         }

            2、啟動線程
            1 HANDLE CBarView::StartPromptThread()
            2 {
            3     LOG("啟動導(dǎo)入數(shù)據(jù)提示線程");
            4     CWinThread* hThread = AfxBeginThread((AFX_THREADPROC)CBarView::RunPromptDialog,(LPVOID)this);
            5 
            6     return (m_hPromptThread = hThread->m_hThread);
            7 }

            3、線程函數(shù)
             1 DWORD WINAPI CBarView::RunPromptDialog(LPVOID Param)
             2 
             3      CBarView* barObj = (CBarView*)Param;
             4     barObj->waitObj = new CImportDataPromptDialog(); 
             5     barObj->waitObj->Create(IDD_DIALOGPROMPT, NULL);
             6 
             7     barObj->waitObj->ShowWindow(SW_SHOW);
             8  
             9     barObj->m_bStopMsg = FALSE;
            10     return 0;
            11 }

            4、結(jié)束線程函數(shù)
             1 void CBarView::StopThread()
             2 {
             3     if (NULL != waitObj)
             4     {
             5         delete waitObj;
             6     }
             7 
             8     if (m_hPromptThread != NULL)
             9     {
            10         ::TerminateThread(m_hPromptThread, 0 );
            11         m_hPromptThread = NULL;
            12         LOG("結(jié)束導(dǎo)入數(shù)據(jù)提示線程");
            13     }
            14 }

            以下轉(zhuǎn)自:http://blog.csdn.net/hellothere/article/details/1788310

            Windows多線程與對話框  

            Windows的對話框是獲取信息輸入的主要手段,增加線程則是獲得更好UI響應(yīng)的重要方式。由于Windows在處理對話框時進行線程調(diào)度的特殊性,如果不對此加以特別注意,增加線程可能不能帶來UI響應(yīng)的改善。

            1         跨線程創(chuàng)建對話框

            1.1      需求

            有這樣的應(yīng)用場景:創(chuàng)建非模態(tài)對話框后需要馬上做些耗時的工作,而同時又希望能夠立刻在對話框上操作,所以,希望讓非模態(tài)對話框工作在單獨的線程上。

            1.2      方案

            主線程啟動一個UI線程,并且,讓這個線程創(chuàng)建非模態(tài)對話框。

            想法是:既然用單獨的線程創(chuàng)建了對話框,所以,主線程在創(chuàng)建UI線程后,就可以繼續(xù)自己其他耗時的工作了。

            1.3      實現(xiàn)

            用一個簡單的例子程序來試驗這個方案:在VC++中創(chuàng)建一個基于SDIMFC應(yīng)用程序,在其CView派生類中處理“Call”菜單命令,創(chuàng)建派生自CWinThreadUI線程,在這個UI線程初始化過程中創(chuàng)建一個對話框。

            1.3.1      單獨的UI線程創(chuàng)建對話框

            實現(xiàn)一個派生自CWinThreadUI線程類,其中最關(guān)鍵的是CreateMyDlgDestroyMyDlg函數(shù)。

            類如下

            class UIWorker : public CWinThread

            {

                DECLARE_DYNCREATE(UIWorker)

            protected:

                UIWorker();       // protected constructor used by dynamic creation

            // Attributes

            public:

            // Operations

            public:

                bool CreateMyDlg( void );

                void SetOwnerWnd( HWND hWnd );

                void DestroyMyDlg( void );

            ……   

            private:

                CDlgUserTest* m_pDlgTest;

                HWND m_hOwnerWnd;

            };

             

            CreateMyDlgDestroyMyDlg的實現(xiàn)都非常簡單

            bool UIWorker::CreateMyDlg( void )

            {

                m_pDlgTest = new CDlgUserTest;

                if ( NULL == m_pDlgTest )

                {

                    return false;

                }

                CWnd* pWnd = NULL;

                if ( NULL != m_hOwnerWnd )

                {

                    pWnd = reinterpret_cast<CWnd*>( CWnd::FromHandle( m_hOwnerWnd ));

                    if ( NULL == pWnd )

                    {

                        return false;

                    }

                }

                BOOL bSuccess = m_pDlgTest->Create( IDD_DIALOG_TEST, pWnd );

                if ( bSuccess )

                {

                    bSuccess = m_pDlgTest->ShowWindow( SW_SHOW );

                }    

                return bSuccess?true:false;

            }

            void UIWorker::DestroyMyDlg( void )

            {  

                if ( NULL != m_pDlgTest )

                {

                    delete m_pDlgTest;

                    m_pDlgTest = NULL;

                }

            }

             

            1.3.2      主線程創(chuàng)建UI線程

            主線程就更加簡單了。在菜單的對應(yīng)操作中,創(chuàng)建線程,為了表示主線程繼續(xù)工作,提供一個循環(huán)。

            bool CUserView::Call(void)

            {

                m_pUIWorker = static_cast<UIWorker*>( AfxBeginThread(

                    RUNTIME_CLASS( UIWorker )));

                for ( int i = 0; i < 100000; ++i )

                    for ( int j = 0; j < 10000; ++j )

                        ;   

                return true;

            }

             

            1.4      結(jié)果:奇怪的延遲

            希望達到的效果是:

            主程序啟動后,顯示一個單文檔視界面,有一個Work菜單

             

            點擊Call菜單后,對話框應(yīng)該馬上彈出,顯示為:

             

            執(zhí)行中,對話框不會馬上彈出,而會等待一定的時間,直到循環(huán)結(jié)束,CUserViewCall函數(shù)返回,對話框才會彈出。等待的時間和循環(huán)的長短成正比。

            2         問題分析

            2.1      不單純的對話框:要求Windows作特殊處理

            對話框是一種很不單純的窗口。無論是創(chuàng)建、消息分發(fā)還是銷毀,Windows都會對對話框做一些特殊的處理。如果用SDK進行對話框編程,就會發(fā)現(xiàn)創(chuàng)建對話框需要專門的Win32 API。而且,我們查閱平臺SDK的講述時,也會發(fā)現(xiàn)對話框需要Windows進行若干額外的“照顧”。事實上,之所以會出現(xiàn)前述的“延遲”情況,就是Windows進行額外協(xié)調(diào)的結(jié)果。

            2.2      窗口協(xié)調(diào)導(dǎo)致等待

            2.2.1      Windows協(xié)調(diào)對話框彈出過程

            使用SPY++研究窗口消息,會發(fā)現(xiàn)非模態(tài)對話框創(chuàng)建時,原來擁有焦點的窗口會收到WM_KILLFOCUS消息,而且獲得焦點的窗口是創(chuàng)建的對話框。

            2.2.2      線程需要分發(fā)消息,不能堵塞

            根據(jù)例子來看,這個窗口焦點的協(xié)調(diào)過程被上升到了線程協(xié)調(diào)的層次。現(xiàn)象就是:如果被去激活的窗口的線程被阻塞,不能立刻處理WM_KILLFOCUS消息的話,創(chuàng)建對話框的線程也會被阻塞,對話框一直不能被顯示出來,直到線程不再阻塞,WM_KILLFOCUS被分發(fā)和處理。

            2.3      解決方案

            這個問題產(chǎn)生的原因是:在主線程繁忙的時候有主線程必須要處理的消息,也就是主線程消息循環(huán)因為窗口處理函數(shù)占用時間過長而被阻塞。因此,這個問題更多是一個設(shè)計問題而非技術(shù)難點。也許,我們該問的是:

            n         我真的要用一個冗長的工作來阻塞主線程這樣長的時間嗎?

            n         我是否可以在單獨的一個工作者線程中來處理這個長的工作?

            考慮了其他的可能性后,如果對上述問題的答案仍然為“是”的話,可以采取以下解決方案:因為我們?nèi)鄙俚氖窍⒀h(huán),所以,加上消息循環(huán),讓對話框能夠顯示出來之后,再去進行其他工作的處理。

            bool CUserView::Call(void)

            {

                m_pUIWorker = static_cast<UIWorker*>( AfxBeginThread(

                    RUNTIME_CLASS( UIWorker )));  

                while ( !m_pUIWorker->GetDoneFlag())

                {

                    MSG msg;

                    ::GetMessage( &msg, this->m_hWnd, NULL, NULL );

                    ::TranslateMessage( &msg );

                    ::DispatchMessage( &msg );

                }

                for ( int i = 0; i < 100000; ++i )

                    for ( int j = 0; j < 10000; ++j )

                        ;   

                return true;

            }

            紅色的代碼就是加上消息循環(huán)。要注意的是,相應(yīng)的線程類里面應(yīng)該在顯示出對話框后設(shè)置一個標志,并且讓主線程可以查詢到這個標志,從而終止這個臨時的消息循環(huán)。

            3         啟示

            3.1      Windows線程調(diào)度

            Windows的線程調(diào)度原則對于程序員來說非常簡單。這條原則是:程序員無法決定線程調(diào)度過程。

            只是因為“程序員無法決定線程調(diào)度過程”,并不意味著程序員不應(yīng)該去了解一些特別的線程調(diào)度過程。在某些場合下,正如上面在和對話框相關(guān)的某些時機,也許,Windows的線程調(diào)度是有明確規(guī)則的。所以,大多數(shù)情況下,程序員可以認為Windows的線程調(diào)度對于自己來說是一個黑盒。但是,某些時候,這個盒子中間發(fā)生的事情也需要了解和掌握。

            3.2      對話框

            對話框是一個古老的話題,很多的人仔細討論了對話框的方方面面。對話框一直是Windows里面非常特殊的一種窗口。它的消息循環(huán),與其他窗口的協(xié)調(diào)要求,都和普通的窗口有不同之處。因此,為了配合這些不同之處,Windows在線程協(xié)調(diào)上也做了一些手腳。

            3.3      多線程編程更多是一種設(shè)計

            更重要的啟示是:多線程需要更多的考慮設(shè)計。

            毫無疑問,多線程可以使多種工作并行進行,提高工作效率,改善界面響應(yīng)。然而,多線程應(yīng)用中一個麻煩的問題是:決定對哪些工作使用單獨的線程。這個決定過程其實就是設(shè)計過程。如果設(shè)計方案不合理,比如,如本例子中反映出來的問題——在主線程被長時間的工作阻塞的情況下,增加的線程并不會給我們帶來明顯的響應(yīng)改善。而且,如果設(shè)計方案不合理,會帶來更多的“臨時機制”的采用,如本例中必須增加一個單獨的消息循環(huán),并且需要在兩個線程中就對話框是否創(chuàng)建出來進行通訊。這樣的實現(xiàn)在很大程度上削減了希望用多線程帶來的好處。

            posted on 2012-08-20 12:45 王海光 閱讀(2980) 評論(0)  編輯 收藏 引用 所屬分類: MFC
            婷婷久久综合| 久久久久久久久久久久中文字幕 | 成人久久精品一区二区三区| 亚洲国产精品无码久久| 久久精品国产亚洲av影院| 久久精品国产亚洲沈樵| 亚洲午夜精品久久久久久app| 久久久一本精品99久久精品88| 久久亚洲国产欧洲精品一| 久久噜噜久久久精品66| 久久中文骚妇内射| 久久亚洲天堂| 国产A级毛片久久久精品毛片| 欧美精品九九99久久在观看| 久久亚洲中文字幕精品有坂深雪 | 久久夜色精品国产亚洲| 韩国无遮挡三级久久| 无码国内精品久久综合88 | 久久这里只有精品久久| 久久精品国产乱子伦| 99久久久国产精品免费无卡顿| 国产精品久久久久久久久软件| 久久国产精品二国产精品| 色综合久久久久综合体桃花网| 少妇熟女久久综合网色欲| 久久精品无码一区二区app| 久久综合综合久久97色| 精品久久久久久无码专区不卡| 97视频久久久| 久久99久久99精品免视看动漫| 深夜久久AAAAA级毛片免费看| 久久黄视频| 久久精品国产一区| 精品国产一区二区三区久久| 亚洲国产精品无码久久久不卡| 日韩人妻无码精品久久免费一| 久久亚洲精精品中文字幕| 国内精品久久久久影院薰衣草| 亚洲综合熟女久久久30p| 日韩精品久久久久久免费| 久久99国产综合精品女同|