• <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>
            posts - 131, comments - 12, trackbacks - 0, articles - 0
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            開源中國社區
            http://www.oschina.net/

            美國
            http://sourceforge.net/



             Ptypes一個開源輕量級的c++庫,包括對一些I/O操作、網絡通信、多線程和異常處理的封裝。雖然代碼有限,包括的內容不少,麻雀雖小,五臟俱全。
                提高:STL Boost和STL ACE
                Boost庫是一個可移植、提供源代碼的C++庫,作為標準庫的后備,是C++標準化進程的發動機之一。 Boost庫由C++標準委員會庫工作組成員發起,其中有些內容有望成為下一代C++標準庫內容。在C++社區中影響甚大,是不折不扣的“準”標準庫。 Boost由于其對跨平臺的強調,對標準C++的強調,與編寫平臺無關。大部分boost庫功能的使用只需包括相應頭文件即可,少數(如正則表達式庫,文 件系統庫等)需要鏈接庫。但Boost中也有很多是實驗性質的東西,在實際的開發中實用需要謹慎。boost 在一些播放軟件和音效中指增強,比如Bass Boost,低音增強。
                Adaptive Communication Environment(自適配通信環境),簡稱ACE。為一個以C++的Template技術所做成的開放源代碼的可跨平臺的網絡應用程序的程序庫套件。它提供了socket/threading/memory management等多種系統調用的面對對象的wrapper,使C++通信軟件開發更加簡單。

            http://m.shnenglu.com/


            個人覺得比較經典的C++ 開源項目,整理如下:

             

            1 、log4cplus

            log4cplus 是C++ 編寫的開源的日志系統, 功能非常全面。C++ 版的log4j

            網址:http://log4cplus.sourceforge.net/

             

            2 、Glog

            Google Glog 是一個C++ 語言的應用級日志記錄框架,提供了 C++ 風格的流操作和各種助手宏。

            SVN :http://google-glog.googlecode.com/svn/trunk

             

            3 、memcached

            memcached 是一套分布式的快取系統,當初是Danga Interactive 為了LiveJournal 所發展的,但目前被許多軟件(如MediaWiki )所使用。這是一套開放源代碼軟件,以BSD license 授權釋出。

            memcached 缺乏認證以及安全管制,這代表應該將memcached 服務器放置在防火墻后。

            SVN :http://code.sixapart.com/svn/memcached

             


            4 、 TinyXML

            TinyXML 是目前非常流行的一款基于DOM 模型的XML 解析器,簡單易用且小巧 玲瓏,非常適合存儲簡單數據,配置文件,對象序列化等數據量不是很大的操作

            網址:http://www.grinninglizard.com/tinyxml/

             

            5 、OpenSSL

            OpenSSL 包含一個命令行工具用來完成OpenSSL 庫中的所有功能,更好的是,它可能已經安裝到你的系統中了。

            OpenSSL 是一個強大的安全套接字層密碼庫,Apache 使用它加密HTTPS ,OpenSSH 使用它加密SSH ,但是,你不應該只將其作為一個庫來使用,它還是一個多用途的、跨平臺的密碼工具。

            網址:http://www.openssl.org/source/

             

            6 、xerces

            Xerces是由Apache組織所推動的一項XML文檔解析開源項目,它目前有多種語言版本包括JAVA、C++、PERL、COM等。

              網址:http://xerces.apache.org/xerces-c/download.cgi

             

            7 、Boost

            Boost 庫是一個經過千錘百煉、可移植、提供源代碼的C++ 庫,作為標準庫的后備,是C++ 標準化進程的發動機之一。 Boost 庫由C++標準委員會庫工作組成員發起,在C++ 社區中影響甚大,其成員已近2000 人。 Boost 庫為我們帶來了最新、最酷、最實用的技術,是不折不扣的“ 準” 標準庫。

            網址:http://www.boost.org/

             


            8、Zlib

            Zlib 軟件包包含 zlib 庫,很多程序中的壓縮或者解壓縮函數都會用到這個庫

            網址:http://www.zlib.net/

             

            里面有幾個好的開源項目比如日志系統,還有XML解析的程序,應該都是不錯的程序,我們應該能從中學習到些什么,然后用到項目中去,或者添加功能到里面去。如果有時間的話,真想靜下心來看一看。

            posted @ 2013-02-16 15:41 盛勝 閱讀(294) | 評論 (0)編輯 收藏

                 摘要: 12345678910111213141516171819202122#include <stdio.h>#include <io.h>  int main (void){    _finddata_t fileDir;    ...  閱讀全文

            posted @ 2013-02-16 15:26 盛勝 閱讀(442) | 評論 (0)編輯 收藏

            IGraphBuilder *m_pGraph ;
            IMediaControl *m_pControl ;
            IMediaEvent   *m_pEvent ;
            CString strfilepath;
            CFileDialog FileDlg(TRUE, NULL, NULL, OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,"Video Files(*.avi;*.avi)|*.avi;*.avi||");
            if(FileDlg.DoModal()==IDOK)
            {
            strfilepath = FileDlg.GetPathName();
            }
            else
            {
            return ;
            }
            m_bstr = strfilepath;
            m_pGraph = NULL;
            m_pControl = NULL;
            m_pEvent = NULL;
            // Initialize the COM library.
            m_hr = CoInitialize(NULL);
            if (FAILED(m_hr))
            {
            printf("ERROR - Could not initialize COM library");
            return;
            }
             
            // Create the filter graph manager and query for interfaces.
            m_hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
            IID_IGraphBuilder, (void **)&m_pGraph);
            if (FAILED(m_hr))
            {
            printf("ERROR - Could not create the Filter Graph Manager.");
            return;
            }
             
            m_hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m_pControl);
            m_hr = m_pGraph->QueryInterface(IID_IMediaEvent, (void **)&m_pEvent);
            // Build the graph. IMPORTANT: Change this string to a file on your system.
            m_hr = m_pGraph->RenderFile(m_bstr, NULL);
            if (SUCCEEDED(m_hr))
            {
            // Run the graph.
            m_hr = m_pControl->Run();
            if (SUCCEEDED(m_hr))
            {
            // Wait for completion.
            long evCode;
            m_pEvent->WaitForCompletion(INFINITE, &evCode);
             
            // Note: Do not use INFINITE in a real application, because it
            // can block indefinitely.
            }
            }
            m_pControl->Release();
            m_pEvent->Release();
            m_pGraph->Release();
            CoUninitialize();

            posted @ 2013-01-22 09:33 盛勝 閱讀(345) | 評論 (0)編輯 收藏

            #include "comutil.h"
            #pragma comment(lib, "comsupp.lib")
            #pragma comment(lib, "comsuppw.lib")

            _bstr_t bstr;
            bstr = strPath;
            ShellExecute(m_hWnd, "open", bstr, NULL, NULL, SW_SHOWNORMAL);

            posted @ 2013-01-18 17:18 盛勝 閱讀(312) | 評論 (0)編輯 收藏

            CWnd *pWnd = CWnd::FromHandle(GetDlgItem(hWnd,ID));
            m_Camerapwnd = pWnd;

            posted @ 2013-01-16 14:01 盛勝 閱讀(241) | 評論 (0)編輯 收藏

            網上很多都說錄制了之后視頻文件為0k,或者是打不開。

            其實,這個原因主要與2方面有關:

              1. OpenCV生成的視頻的編碼格式有關。

              2. 非法退出錄取有關(我用200次循環解決。或者可以用Timer?;蛘哂闷渌I處理)

             

            vs2008 win32控制臺程序

            復制代碼
             1 #include "cv.h"
            2 #include "cxcore.h"
            3 #include "highgui.h"
            4 #include <iostream>
            5
            6 using namespace std;
            7 int main()
            8 {
            9 CvCapture* capture=cvCaptureFromCAM(-1);
            10 CvVideoWriter* video=NULL;
            11 IplImage* frame=NULL;
            12 int n;
            13 if(!capture) //如果不能打開攝像頭給出警告
            14 {
            15 cout<<"Can not open the camera."<<endl;
            16 return -1;
            17 }
            18 else
            19 {
            20 frame=cvQueryFrame(capture); //首先取得攝像頭中的一幀
            21 video=cvCreateVideoWriter("camera.avi", CV_FOURCC('X', 'V', 'I', 'D'), 25,
            22 cvSize(frame->width,frame->height)); //創建CvVideoWriter對象并分配空間
            23 //保存的文件名為camera.avi,編碼要在運行程序時選擇,大小就是攝像頭視頻的大小,幀頻率是32
            24 if(video) //如果能創建CvVideoWriter對象則表明成功
            25 {
            26 cout<<"VideoWriter has created."<<endl;
            27 }
            28
            29 cvNamedWindow("Camera Video",1); //新建一個窗口
            30 int i = 0;
            31 while(i <= 200) // 讓它循環200次自動停止錄取
            32 {
            33 frame=cvQueryFrame(capture); //從CvCapture中獲得一幀
            34 if(!frame)
            35 {
            36 cout<<"Can not get frame from the capture."<<endl;
            37 break;
            38 }
            39 n=cvWriteFrame(video,frame); //判斷是否寫入成功,如果返回的是1,表示寫入成功
            40 cout<<n<<endl;
            41 cvShowImage("Camera Video",frame); //顯示視頻內容的圖片
            42 i++;
            43 if(cvWaitKey(2)>0)
            44 break; //有其他鍵盤響應,則退出
            45 }
            46
            47 cvReleaseVideoWriter(&video);
            48 cvReleaseCapture(&capture);
            49 cvDestroyWindow("Camera Video");
            50 }
            51 return 0;
            52 }

            posted @ 2013-01-16 11:18 盛勝 閱讀(9945) | 評論 (4)編輯 收藏

            http://blog.csdn.net/weixingstudio/article/details/7360941

            posted @ 2013-01-15 16:30 盛勝 閱讀(291) | 評論 (0)編輯 收藏

            http://hi.baidu.com/andywangcn/item/50d640c325290a2aef4665c4
            1、 啟動線程:

            CWinThread* AfxBeginThread( 線程函數,this );

            2、通常導致線程終止的兩種情況是:控制函數退出或不允許線程完成運行。如果字處理器使用后臺打印線程,若成功完成打印,則控制函數將正常終止。但是,如果用戶要取消打印,后臺打印線程則不得不提前終止。本主題介紹如何實現每一種情況,以及在終止后如何獲取線程的退出代碼。

            (1)正常線程終止

            對于輔助線程,正常線程終止很簡單:退出控制函數并返回表示終止原因的值。可以使用 函數或 return 語句。一般情況下,0 表示成功完成,但這取決于您自己。

            對于用戶界面線程,該過程也很簡單:從用戶界面線程內調用 Platform SDK 中的 。PostQuitMessage 采用的唯一參數是線程的退出代碼。對于輔助線程,0 通常表示成功完成。

            (2)過早的線程終止

            過早終止線程幾乎一樣簡單:從線程內調用 。將所需的退出代碼作為唯一參數傳遞。這將停止執行線程、解除對線程堆棧的分配、分離附加到線程的所有 DLL 并從內存中刪除線程對象。

            必須從要終止的線程內調用 AfxEndThread。如果要從其他線程終止線程,必須設置兩個線程間的通信方法。

            舉一個例子:

            可以創建一個信號量,用WaitForSingleObject函數來檢測該信號量的狀態。

            成員變量 m_hThreadEvent;

            m_hThreadEvent = CreateEvent( NULL, FALSE, FALSE, NULL );

            線程的執行函數:

                     for ( ; ; )

                     {         DWORD dwRetVal;

                               dwRetVal = WaitForSingleObject( m_hThreadEvent, 100 );

                               if ( dwRetVal == WAIT_TIMEOUT )

                                    {                    // TODO:

                               }

                               else

                               {

                                        // stop receive text thread.

                                        DWORD dwExitCode;

                                        GetExitCodeThread( m_pThreadRecv->m_hThread, &dwExitCode );

                                        AfxEndThread( dwExitCode, TRUE );

                               }

                     }

                要結束線程時,使用SetEvent,將信號量置為有信號。

                該線程是在信號量有信號時,退出。

            (3)TerminateThread

            在CWinThread對象中有線程的句柄,可以使用該句柄強行殺死線程。但是不推薦使用這種方式,當可以正常結束的時候,選擇前兩種方法較好。

            檢索線程的退出代碼

            若要獲取輔助線程或用戶界面線程的退出代碼,請調用 函數。有關此函數的信息,請參見 Platform SDK。此函數獲取線程(存儲在 CWinThread 對象的 m_hThread 數據成員中)的句柄和 DWORD 的地址。

            如果線程仍然是活動的,GetExitCodeThread 將 STILL_ACTIVE 放置在提供的 DWORD 地址中;否則將退出代碼放置在該地址中。

            檢索 對象的退出代碼還需要一步。默認情況下,當 CWinThread 線程終止時,刪除該線程對象。這意味著不能訪問 m_hThread 數據成員,因為 CWinThread 對象不再存在。若要避免出現這種情況,請執行以下操作之一:

            • 將 m_bAutoDelete 數據成員設置為 FALSE。這使 CWinThread 對象在線程終止后仍可以繼續存在。然后可以在線程終止后,訪問 m_hThread 數據成員。但是,如果使用此方法,就得銷毀 CWinThread 對象,因為框架不會自動刪除該對象。這是首選方法。

            • 單獨存儲線程的句柄。創建線程后,(使用 ::DuplicateHandle)將其 m_hThread 數據成員復制到其他變量,并通過該變量訪問該成員。這樣,終止后即會自動刪除對象,并且仍然可以找到線程終止的原因。請注意:在可以復制句柄之前,線程不終止。執行此操作的最安全的方式是將 CREATE_SUSPENDED 傳遞到 ,存儲句柄,然后通過調用 繼續執行線程。

            任一方法都可以使您確定 CWinThread 對象終止的原因。

            posted @ 2013-01-15 11:00 盛勝 閱讀(9827) | 評論 (0)編輯 收藏

            http://www.cnblogs.com/zqrferrari/archive/2010/07/07/1773113.html
            MFC 多線程及線程同步

            一、MFC對多線程編程的支持

              MFC中有兩類線程,分別稱之為工作者線程和用戶界面線程。二者的主要區別在于工作者線程沒有消息循環,而用戶界面線程有自己的消息隊列和消息循環。
              工作者線程沒有消息機制,通常用來執行后臺計算和維護任務,如冗長的計算過程,打印機的后臺打印等。用戶界面線程一般用于處理獨立于其他線程執行之外的用戶輸入,響應用戶及系統所產生的事件和消息等。但對于Win32的API編程而言,這兩種線程是沒有區別的,它們都只需線程的啟動地址即可啟動線程來執行任務。
              在MFC中,一般用全局函數AfxBeginThread()來創建并初始化一個線程的運行,該函數有兩種重載形式,分別用于創建工作者線程和用戶界面線程。兩種重載函數原型和參數分別說明如下:

              (1) CWinThread* AfxBeginThread(

                    AFX_THREADPROC pfnThreadProc,
                        LPVOID pParam,
                        int nPriority = THREAD_PRIORITY_NORMAL,
                        UNT nStackSize = 0,
                        DWORD dwCreateFlags = 0,
                        LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
                       );//用于創建工作者線程

              PfnThreadProc:指向工作者線程的執行函數的指針,線程函數原型必須聲明如下:

              UINT ExecutingFunction(LPVOID pParam);

              請注意,ExecutingFunction()應返回一個UINT類型的值,用以指明該函數結束的原因。一般情況下,返回0表明執行成功。

            • pParam:      一個32位參數,執行函數將用某種方式解釋該值。它可以是數值,或是指向一個結構的指針,甚至可以被忽略;
            • nPriority:     線程的優先級。如果為0,則線程與其父線程具有相同的優先級;
            • nStackSize:   線程為自己分配堆棧的大小,其單位為字節。如果nStackSize被設為0,則線程的堆棧被設置成與父線程堆棧相同大?。?/span>
            • dwCreateFlags:如果為0,則線程在創建后立刻開始執行。如果為CREATE_SUSPEND,則線程在創建后立刻被掛起;
            • lpSecurityAttrs:線程的安全屬性指針,一般為NULL;

              (2) CWinThread* AfxBeginThread(

                   CRuntimeClass* pThreadClass,
                        int nPriority = THREAD_PRIORITY_NORMAL,
                        UNT nStackSize = 0,
                        DWORD dwCreateFlags = 0,
                        LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL
                       ); 

              pThreadClass 是指向 CWinThread 的一個導出類的運行時類對象的指針,該導出類定義了被創建的用戶界面線程的啟動、退出等;其它參數的意義同形式1。使用函數的這個原型生成的線程也有消息機制,在以后的例子中我們將發現同主線程的機制幾乎一樣。

              下面我們對CWinThread類的數據成員及常用函數進行簡要說明。

            • m_hThread:     當前線程的句柄;
            • m_nThreadID:   當前線程的ID;
            • m_pMainWnd: 指向應用程序主窗口的指針
              BOOL CWinThread::CreateThread(DWORD dwCreateFlags=0,UINT nStackSize=0,LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);

              該函數中的dwCreateFlags、nStackSize、lpSecurityAttrs參數和API函數CreateThread中的對應參數有相同含義,該函數執行成功,返回非0值,否則返回0。
              一般情況下,調用AfxBeginThread()來一次性地創建并啟動一個線程,但是也可以通過兩步法來創建線程:首先創建CWinThread類的一個對象,然后調用該對象的成員函數CreateThread()來啟動該線程。

              virtual BOOL CWinThread::InitInstance();

              重載該函數以控制用戶界面線程實例的初始化。初始化成功則返回非0值,否則返回0。用戶界面線程經常重載該函數,工作者線程一般不使用InitInstance()。

              virtual int CWinThread::ExitInstance();

              在線程終結前重載該函數進行一些必要的清理工作。該函數返回線程的退出碼,0表示執行成功,非0值用來標識各種錯誤。同InitInstance()成員函數一樣,該函數也只適用于用戶界面線程。

             

            二、MFC中線程同步

             在程序中使用多線程時,一般很少有多個線程能在其生命期內進行完全獨立的操作。更多的情況是一些線程進行某些處理操作,而其他的線程必須對其處理結果進行了解。正常情況下對這種處理結果的了解應當在其處理任務完成后進行。
              如果不采取適當的措施,其他線程往往會在線程處理任務結束前就去訪問處理結果,這就很有可能得到有關處理結果的錯誤了解。例如,多個線程同時訪問同一個全局變量,如果都是讀取操作,則不會出現問題。如果一個線程負責改變此變量的值,而其他線程負責同時讀取變量內容,則不能保證讀取到的數據是經過寫線程修改后的。
              為了確保讀線程讀取到的是經過修改的變量,就必須在向變量寫入數據時禁止其他線程對其的任何訪問,直至賦值過程結束后再解除對其他線程的訪問限制。象這種保證線程能了解其他線程任務處理結束后的處理結果而采取的保護措施即為線程同步。
              線程的同步可分用戶模式的線程同步和內核對象的線程同步兩大類。用戶模式中線程的同步方法主要有原子訪問和臨界區等方法。其特點是同步速度特別快,適合于對線程運行速度有嚴格要求的場合。
              內核對象的線程同步則主要由事件、等待定時器、信號量以及信號燈等內核對象構成。由于這種同步機制使用了內核對象,使用時必須將線程從用戶模式切換到內核模式,而這種轉換一般要耗費近千個CPU周期,因此同步速度較慢,但在適用性上卻要遠優于用戶模式的線程同步方式。

              

              1.臨界區
             
             臨界區(Critical Section)是一段獨占對某些共享資源訪問的代碼,在任意時刻只允許一個線程對共享資源進行訪問。如果有多個線程試圖同時訪問臨界區,那么在有一個線程進入后其他所有試圖訪問此臨界區的線程將被掛起,并一直持續到進入臨界區的線程離開。臨界區在被釋放后,其他線程可以繼續搶占,并以此達到用原子方式操作共享資源的目的。
              臨界區在使用時以CRITICAL_SECTION結構對象保護共享資源,并分別用EnterCriticalSection()和LeaveCriticalSection()函數去標識和釋放一個臨界區。所用到的CRITICAL_SECTION結構對象必須經過InitializeCriticalSection()的初始化后才能使用,而且必須確保所有線程中的任何試圖訪問此共享資源的代碼都處在此臨界區的保護之下。否則臨界區將不會起到應有的作用,共享資源依然有被破壞的可能。

            代碼
              在使用臨界區時,一般不允許其運行時間過長,只要進入臨界區的線程還沒有離開,其他所有試圖進入此臨界區的線程都會被掛起而進入到等待狀態,并會在一定程度上影響。程序的運行性能。尤其需要注意的是不要將等待用戶輸入或是其他一些外界干預的操作包含到臨界區。如果進入了臨界區卻一直沒有釋放,同樣也會引起其他線程的長時間等待。換句話說,在執行了EnterCriticalSection()語句進入臨界區后無論發生什么,必須確保與之匹配的LeaveCriticalSection()都能夠被執行到??梢酝ㄟ^添加結構化異常處理代碼來確保LeaveCriticalSection()語句的執行。雖然臨界區同步速度很快,但卻只能用來同步本進程內的線程,而不可用來同步多個進程中的線程。
              MFC為臨界區提供有一個CCriticalSection類,使用該類進行線程同步處理是非常簡單的,只需在線程函數中用CCriticalSection類成員函數Lock()和UnLock()標定出被保護代碼片段即可。對于上述代碼,可通過CCriticalSection類將其改寫如下:

            代碼

             

              2.事件內核對象

              在前面講述線程通信時曾使用過事件內核對象來進行線程間的通信,除此之外,事件內核對象也可以通過通知操作的方式來保持線程的同步。對于前面那段使用臨界區保持線程同步的代碼可用事件對象的線程同步方法改寫如下:

            代碼

              在創建線程前,首先創建一個可以自動復位的事件內核對象hEvent,而線程函數則通過WaitForSingleObject()等待函數無限等待hEvent的置位,只有在事件置位時WaitForSingleObject()才會返回,被保護的代碼將得以執行。對于以自動復位方式創建的事件對象,在其置位后一被WaitForSingleObject()等待到就會立即復位,也就是說在執行ThreadProc12()中的受保護代碼時,事件對象已經是復位狀態的,這時即使有ThreadProc13()對CPU的搶占,也會由于WaitForSingleObject()沒有hEvent的置位而不能繼續執行,也就沒有可能破壞受保護的共享資源。在ThreadProc12()中的處理完成后可以通過SetEvent()對hEvent的置位而允許ThreadProc13()對共享資源g_cArray的處理。這里SetEvent()所起的作用可以看作是對某項特定任務完成的通知。
              使用臨界區只能同步同一進程中的線程,而使用事件內核對象則可以對進程外的線程進行同步,其前提是得到對此事件對象的訪問權??梢酝ㄟ^OpenEvent()函數獲取得到,其函數原型為:

            HANDLE OpenEvent(
             DWORD dwDesiredAccess,  
            // 訪問標志
             BOOL bInheritHandle,    // 繼承標志
             LPCTSTR lpName          // 指向事件對象名的指針
            ); 
              如果事件對象已創建(在創建事件時需要指定事件名),函數將返回指定事件的句柄。對于那些在創建事件時沒有指定事件名的事件內核對象,可以通過使用內核對象的繼承性或是調用DuplicateHandle()函數來調用CreateEvent()以獲得對指定事件對象的訪問權。在獲取到訪問權后所進行的同步操作與在同一個進程中所進行的線程同步操作是一樣的。
              如果需要在一個線程中等待多個事件,則用WaitForMultipleObjects()來等待。WaitForMultipleObjects()與WaitForSingleObject()類似,同時監視位于句柄數組中的所有句柄。這些被監視對象的句柄享有平等的優先權,任何一個句柄都不可能比其他句柄具有更高的優先權。WaitForMultipleObjects()的函數原型為:
            DWORD WaitForMultipleObjects(
             DWORD nCount,              
            // 等待句柄數
             CONST HANDLE *lpHandles,   // 句柄數組首地址
             BOOL fWaitAll,             // 等待標志
             DWORD dwMilliseconds       // 等待時間間隔
            );

              參數nCount指定了要等待的內核對象的數目,存放這些內核對象的數組由lpHandles來指向。fWaitAll對指定的這nCount個內核對象的兩種等待方式進行了指定,為TRUE時當所有對象都被通知時函數才會返回,為FALSE則只要其中任何一個得到通知就可以返回。dwMilliseconds在這里的作用與在WaitForSingleObject()中的作用是完全一致的。如果等待超時,函數將返回WAIT_TIMEOUT。如果返回WAIT_OBJECT_0到WAIT_OBJECT_0+nCount-1中的某個值,則說明所有指定對象的狀態均為已通知狀態(當fWaitAll為TRUE時)或是用以減去WAIT_OBJECT_0而得到發生通知的對象的索引(當fWaitAll為FALSE時)。如果返回值在WAIT_ABANDONED_0與WAIT_ABANDONED_0+nCount-1之間,則表示所有指定對象的狀態均為已通知,且其中至少有一個對象是被丟棄的互斥對象(當fWaitAll為TRUE時),或是用以減去WAIT_OBJECT_0表示一個等待正常結束的互斥對象的索引(當fWaitAll為FALSE時)。 下面給出的代碼主要展示了對WaitForMultipleObjects()函數的使用。通過對兩個事件內核對象的等待來控制線程任務的執行與中途退出:

            代碼

              MFC為事件相關處理也提供了一個CEvent類,共包含有除構造函數外的4個成員函數PulseEvent()、ResetEvent()、SetEvent()和UnLock()。在功能上分別相當與Win32 API的PulseEvent()、ResetEvent()、SetEvent()和CloseHandle()等函數。而構造函數則履行了原CreateEvent()函數創建事件對象的職責,其函數原型為:
              CEvent(BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );

             

              3.信號量內核對象

              信號量(Semaphore)內核對象對線程的同步方式與前面幾種方法不同,它允許多個線程在同一時刻訪問同一資源,但是需要限制在同一時刻訪問此資源的最大線程數目。在用CreateSemaphore()創建信號量時即要同時指出允許的最大資源計數和當前可用資源計數。一般是將當前可用資源計數設置為最大資源計數,每增加一個線程對共享資源的訪問,當前可用資源計數就會減1,只要當前可用資源計數是大于0的,就可以發出信號量信號。但是當前可用計數減小到0時則說明當前占用資源的線程數已經達到了所允許的最大數目,不能在允許其他線程的進入,此時的信號量信號將無法發出。線程在處理完共享資源后,應在離開的同時通過ReleaseSemaphore()函數將當前可用資源計數加1。在任何時候當前可用資源計數決不可能大于最大資源計數。
              使用信號量內核對象進行線程同步主要會用到CreateSemaphore()、OpenSemaphore()、ReleaseSemaphore()、WaitForSingleObject()和WaitForMultipleObjects()等函數。其中,CreateSemaphore()用來創建一個信號量內核對象,其函數原型為:

            HANDLE CreateSemaphore(
             LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, 
            // 安全屬性指針
             LONG lInitialCount,               // 初始計數
             LONG lMaximumCount,               // 最大計數
             LPCTSTR lpName                  // 對象名指針
            );  

              參數lMaximumCount是一個有符號32位值,定義了允許的最大資源計數,最大取值不能超過4294967295。lpName參數可以為創建的信號量定義一個名字,由于其創建的是一個內核對象,因此在其他進程中可以通過該名字而得到此信號量。OpenSemaphore()函數即可用來根據信號量名打開在其他進程中創建的信號量,函數原型如下:

            HANDLE OpenSemaphore(
             DWORD dwDesiredAccess,   
            // 訪問標志
             BOOL bInheritHandle,    // 繼承標志
             LPCTSTR lpName        // 信號量名
            ); 

              在線程離開對共享資源的處理時,必須通過ReleaseSemaphore()來增加當前可用資源計數。否則將會出現當前正在處理共享資源的實際線程數并沒有達到要限制的數值,而其他線程卻因為當前可用資源計數為0而仍無法進入的情況。ReleaseSemaphore()的函數原型為:

            BOOL ReleaseSemaphore(
             HANDLE hSemaphore, 
               // 信號量句柄
             LONG lReleaseCount,   // 計數遞增數量
             LPLONG lpPreviousCount  // 先前計數
            );

              該函數將lReleaseCount中的值添加給信號量的當前資源計數,一般將lReleaseCount設置為1,如果需要也可以設置其他的值。WaitForSingleObject()和WaitForMultipleObjects()主要用在試圖進入共享資源的線程函數入口處,主要用來判斷信號量的當前可用資源計數是否允許本線程的進入。只有在當前可用資源計數值大于0時,被監視的信號量內核對象才會得到通知。
              信號量的使用特點使其更適用于對Socket(套接字)程序中線程的同步。例如,網絡上的HTTP服務器要對同一時間內訪問同一頁面的用戶數加以限制,這時可以為沒一個用戶對服務器的頁面請求設置一個線程,而頁面則是待保護的共享資源,通過使用信號量對線程的同步作用可以確保在任一時刻無論有多少用戶對某一頁面進行訪問,只有不大于設定的最大用戶數目的線程能夠進行訪問,而其他的訪問企圖則被掛起,只有在有用戶退出對此頁面的訪問后才有可能進入。下面給出的示例代碼即展示了類似的處理過程:

            代碼

              在MFC中,通過CSemaphore類對信號量作了表述。該類只具有一個構造函數,可以構造一個信號量對象,并對初始資源計數、最大資源計數、對象名和安全屬性等進行初始化,其原型如下:

               CSemaphore( LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName = NULL, LPSECURITY_ATTRIBUTES lpsaAttributes = NULL );

              在構造了CSemaphore類對象后,任何一個訪問受保護共享資源的線程都必須通過CSemaphore從父類CSyncObject類繼承得到的Lock()和UnLock()成員函數來訪問或釋放CSemaphore對象。與前面介紹的幾種通過MFC類保持線程同步的方法類似,通過CSemaphore類也可以將前面的線程同步代碼進行改寫,這兩種使用信號量的線程同步方法無論是在實現原理上還是從實現結果上都是完全一致的。下面給出經MFC改寫后的信號量線程同步代碼:

            代碼

             

                 4.互斥內核對象

                 互斥(Mutex)是一種用途非常廣泛的內核對象。能夠保證多個線程對同一共享資源的互斥訪問。同臨界區有些類似,只有擁有互斥對象的線程才具有訪問資源的權限,由于互斥對象只有一個,因此就決定了任何情況下此共享資源都不會同時被多個線程所訪問。當前占據資源的線程在任務處理完后應將擁有的互斥對象交出,以便其他線程在獲得后得以訪問資源。與其他幾種內核對象不同,互斥對象在操作系統中擁有特殊代碼,并由操作系統來管理,操作系統甚至還允許其進行一些其他內核對象所不能進行的非常規操作。

                 以互斥內核對象來保持線程同步可能用到的函數主要有CreateMutex()、OpenMutex()、ReleaseMutex()、WaitForSingleObject()和WaitForMultipleObjects()等。在使用互斥對象前,首先要通過CreateMutex()或OpenMutex()創建或打開一個互斥對象。CreateMutex()函數原型為:

                 HANDLE CreateMutex(
                   LPSECURITY_ATTRIBUTES lpMutexAttributes, // 安全屬性指針
                   BOOL bInitialOwner, // 初始擁有者
                   LPCTSTR lpName // 互斥對象名
                 );

                 參數bInitialOwner主要用來控制互斥對象的初始狀態。一般多將其設置為FALSE,以表明互斥對象在創建時并沒有為任何線程所占有。如果在創建互斥對象時指定了對象名,那么可以在本進程其他地方或是在其他進程通過OpenMutex()函數得到此互斥對象的句柄。OpenMutex()函數原型為:

                HANDLE OpenMutex(
                  DWORD dwDesiredAccess, // 訪問標志
                  BOOL bInheritHandle, // 繼承標志
                  LPCTSTR lpName // 互斥對象名
                );

                 當目前對資源具有訪問權的線程不再需要訪問此資源而要離開時,必須通過ReleaseMutex()函數來釋放其擁有的互斥對象,其函數原型為:

                BOOL ReleaseMutex(HANDLE hMutex);

                其唯一的參數hMutex為待釋放的互斥對象句柄。至于WaitForSingleObject()和WaitForMultipleObjects()等待函數在互斥對象保持線程同步中所起的作用與在其他內核對象中的作用是基本一致的,也是等待互斥內核對象的通知。但是這里需要特別指出的是:在互斥對象通知引起調用等待函數返回時,等待函數的返回值不再是通常的WAIT_OBJECT_0(對于WaitForSingleObject()函數)或是在WAIT_OBJECT_0到WAIT_OBJECT_0+nCount-1之間的一個值(對于WaitForMultipleObjects()函數),而是將返回一個WAIT_ABANDONED_0(對于WaitForSingleObject()函數)或是在WAIT_ABANDONED_0到WAIT_ABANDONED_0+nCount-1之間的一個值(對于WaitForMultipleObjects()函數)。以此來表明線程正在等待的互斥對象由另外一個線程所擁有,而此線程卻在使用完共享資源前就已經終止。除此之外,使用互斥對象的方法在等待線程的可調度性上同使用其他幾種內核對象的方法也有所不同,其他內核對象在沒有得到通知時,受調用等待函數的作用,線程將會掛起,同時失去可調度性,而使用互斥的方法卻可以在等待的同時仍具有可調度性,這也正是互斥對象所能完成的非常規操作之一。
              在編寫程序時,互斥對象多用在對那些為多個線程所訪問的內存塊的保護上,可以確保任何線程在處理此內存塊時都對其擁有可靠的獨占訪問權。下面給出的示例代碼即通過互斥內核對象hMutex對共享內存快g_cArray[]進行線程的獨占訪問保護。下面給出實現代碼清單:

            代碼
            復制代碼
            // 互斥對象
            HANDLE hMutex = NULL;
            char g_cArray[10];
            UINT ThreadProc18(LPVOID pParam)
            {
             
            // 等待互斥對象通知
             WaitForSingleObject(hMutex, INFINITE);
             
            // 對共享資源進行寫入操作
             for (int i = 0; i < 10; i++)
             {
              g_cArray[i] 
            = 'a';
              Sleep(
            1);
             }
             
            // 釋放互斥對象
             ReleaseMutex(hMutex);
             
            return 0;
            }
            UINT ThreadProc19(LPVOID pParam)
            {
             
            // 等待互斥對象通知
             WaitForSingleObject(hMutex, INFINITE);
             
            // 對共享資源進行寫入操作
             for (int i = 0; i < 10; i++)
             {
              g_cArray[
            10 - i - 1= 'b';
              Sleep(
            1);
             }
             
            // 釋放互斥對象
             ReleaseMutex(hMutex);
             
            return 0;
            }
            ……
            void CSample08View::OnMutex() 
            {
             
            // 創建互斥對象
             hMutex = CreateMutex(NULL, FALSE, NULL);
             
            // 啟動線程
             AfxBeginThread(ThreadProc18, NULL);
             AfxBeginThread(ThreadProc19, NULL);
             
            // 等待計算完畢
             Sleep(300);
             
            // 報告計算結果
             CString sResult = CString(g_cArray);
             AfxMessageBox(sResult);
            復制代碼

                 互斥對象在MFC中通過CMutex類進行表述。使用CMutex類的方法非常簡單,在構造CMutex類對象的同時可以指明待查詢的互斥對象的名字,在構造函數返回后即可訪問此互斥變量。CMutex類也是只含有構造函數這唯一的成員函數,當完成對互斥對象保護資源的訪問后,可通過調用從父類CSyncObject繼承的UnLock()函數完成對互斥對象的釋放。CMutex類構造函數原型為:
                 CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );

                該類的適用范圍和實現原理與API方式創建的互斥內核對象是完全類似的,但要簡潔的多,下面給出就是對前面的示例代碼經CMutex類改寫后的程序實現清單:

            代碼
            復制代碼
            CMutex g_clsMutex(FALSE, NULL);     // MFC互斥類對象

            UINT ThreadProc27(LPVOID pParam)
            {
             g_clsMutex.Lock();                
            // 等待互斥對象通知

             
            for (int i = 0; i < 10; i++)      // 對共享資源進行寫入操作
             {
              g_cArray[i] 
            = 'a';
              Sleep(
            1);
             }

             g_clsMutex.Unlock();              
            // 釋放互斥對象
             return 0;
            }
            UINT ThreadProc28(LPVOID pParam)
            {
             g_clsMutex.Lock();

             
            for (int i = 0; i < 10; i++)
             {
              g_cArray[
            10 - i - 1= 'b';
              Sleep(
            1);
             }

             g_clsMutex.Unlock();
             
            return 0;
            }
            ……
            void CSample08View::OnMutexMfc() 
            {
             AfxBeginThread(ThreadProc27, NULL);
             AfxBeginThread(ThreadProc28, NULL);

             Sleep(
            300);

             CString sResult 
            = CString(g_cArray);
             AfxMessageBox(sResult);
            }
            復制代碼

            posted @ 2013-01-15 10:02 盛勝 閱讀(466) | 評論 (1)編輯 收藏

            http://hi.baidu.com/xiao%BF%D5%BF%D5/blog/item/3c418716a6cadf12962b4344.html

            CFileDialog打開當前路徑

            TCHAR Buffer[size];

            GetCurrentDirectory(size, Buffer);

            CFileDialog dlg(true,"*BIN",NULL,OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, "二進制文件(*.BIN)|*.bin|All Files (*.*)|*.*|",NULL); 
            dlg.m_ofn.lpstrInitialDir=Buffer;

            if(dlg.DoModal())

            {

            //your code;

            }

             

            ========================

            http://hi.baidu.com/g168999/blog/item/9ef3ab517977f1571038c2ba.html

            VC獲取當前程序文件的路徑,文件名以及路徑2種方法對比建議
            2010-01-01 13:49

            1.方法1

               char pBuf[MAX_PATH];                                               //存放路徑的變量
               GetCurrentDirectory(MAX_PATH,pBuf);                   //獲取程序的當前目錄
               strcat(pBuf,"http://");
               strcat(pBuf,AfxGetApp()->m_pszExeName);   
               strcat(pBuf,".exe");                                                       //獲取程序的全文件名

            2.方法2

               //函數返回應用程序所在的路徑  

               CString    CClientApp::ReturnPath()  

               {   
               CString    sPath;   
               GetModuleFileName(NULL,sPath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);   
               sPath.ReleaseBuffer    ();   
               int    nPos;   
               nPos=sPath.ReverseFind('//');   
               sPath=sPath.Left(nPos);   
               return    sPath;   
               }

            3.對比及建議

            方法1獲取的是程序的工作路徑,如某個程序安裝在C,D盤或者其它任何,當你從[開始]-[程序]后的菜單中打開該文件,此時獲取的是用戶工作路徑,如:C:/Documents and Settings/[計算機當前用戶名]/....../....
            如果你想通過這個路徑來加載你放在程序目錄下的文件,必定出錯。通常這種情況在你編譯調試程序時是不會出錯的,你跟蹤得到的絕對路徑,但打包安裝后一定出問題。

            方法2獲取的是程序的絕對路徑,用這個路徑加載同目錄下的文件是不會有問題的。

            如果你要確保成功加載文件,建議使用方法2?。。。。。?br />

            新建目錄CreateDirectory

            第一個參數值為文件夾名稱,第二個參數值為安全屬性,一般設置為NULL即可。如果正確創建,返回值為1,如果沒有正常創建文件夾,則返回0。

              特別的:該函數每次調用時都只能創建一級文件夾,即文件夾中不能再包含子文件夾。
              當希望創建含有子文件夾的文件夾時,可以先使用該函數創建一級文件夾,然后再使用該函數在一級文件夾下創建子文件夾。如:
              希望創建:d:\\TEST\\temp,
              則:CString str = “d:\\TEST”;
              CreateDirectory(str, NULL);
              str = str + \\temp;
              CreateDirectory(str, NULL);

            1. CString szDir;  
            2. szDir="C:\\temp";//臨時文件夾  
            3. DWORD dwAttr=GetFileAttributes(szDir);  
            4. if(dwAttr==0xFFFFFFFF)  //臨時文件夾不存在則創建  
            5. {  
            6.     CreateDirectory(szDir,NULL);  
            7. )  
            8. //.........chuli  
            9. RemoveDirectory(szDir);//刪除文件夾  

            得到運行程序所在路徑全路徑(exe或其他模塊文件名稱,程序目錄):GetModuleFileName。

            函數原型:

              DWORD GetModuleFileName(
              HMODULE hModule,
              LPTSTR lpFilename,
              DWORD nSize
              );
              函數參數說明:
              hModule HMODULE 裝載一個程序實例的句柄。如果該參數為NULL,該函數返回該當前應用程序全路徑。
              lpFileName LPTSTR 是你存放返回的名字的內存塊的指針,是一個輸出參數
              nSize DWORD ,裝載到緩沖區lpFileName的最大值
              函數返回值:
              如果返回為成功,將在lpFileName的緩沖區當中返回相應模塊的路徑,如果所設的nSize過小,那么返回僅按所設置緩沖區大小返回相應字符串內容。
              如果函數失敗,返回值將為0,利用GetLastError可獲得異常代碼。
              需要的頭文件為:

              windows.h


              
            1. #include <windows.h>  
            2.   #include <stdio.h>  
            3.   BOOL CreateSampleService()  
            4.   {  
            5.   TCHAR szPath[MAX_PATH];  
            6.   if( !GetModuleFileName( NULL, szPath, MAX_PATH ) )  
            7.   {  
            8.   printf("GetModuleFileName failed (%d)\n", GetLastError());  
            9.   return FALSE;  
            10.   }  
            11.   return TRUE;  
            12.   }  
            1. <h1><a name="t2"></a>獲取程序當前路徑GetCurrentDirectory(當前進程的當前路徑,即程序實例目錄,會隨著操作的改變而改變)</h1>DWORD GetCurrentDirectory(  
            2.   DWORD nBufferLength, // size of directory buffer  
            3.   LPTSTR lpBuffer // directory buffer  
            4.   );  

              函數功能
              獲取當前進程的當前目錄
              參數說明
              參數 類型及說明
              nBufferLength 緩沖區的長度
              lpBuffer 指定一個預定義字串,用于裝載當前目錄
              返回值
              調用成功 返回裝載到lpBuffer的字節數。
              如nBufferLength的長度不夠,不足以容納目錄,則返回值是必要的緩沖區長度(要求至少這個長度),其中包括空中止字符。零表示失敗。使用GetLastError函數可獲得錯誤信息

            CFileDialog設置打開默認路徑dlg.m_ofn.lpstrInitialDir="D:\\Program File";

            謹記:CFileDialog會改變程序的默認執行路徑,比較穩妥的辦法還是絕對路徑來訪問文件比較好。在程序剛一跑起來的時候,先用GetCurrentDirectory()或是GetModuleFileName()獲得當前可執行文件所在的路徑,并保存起來。以后即使是用CFileDialog改變了當前的路徑,也能很容易地找回來。

            1. CFileDialog Dlg(TRUE,NULL,NULL,0,"ASCII Data Files(*.asc)|*.asc|所有文件 (*.*)|*.*||");  
            2.     char pBuf[MAX_PATH];                                 //存放路徑的變量         
            3.       
            4.     GetCurrentDirectory(MAX_PATH,pBuf);                   //獲取程序的當前目錄  
            5.       
            6.     strcat(pBuf,"\\");  
            7.       
            8.     CString strtemp=pBuf;  
            9.       
            10.   
            11.     Dlg.m_ofn.lpstrInitialDir=pBuf; 

            posted @ 2013-01-14 14:57 盛勝 閱讀(4578) | 評論 (0)編輯 收藏

            僅列出標題
            共14頁: 1 2 3 4 5 6 7 8 9 Last 
            97精品依人久久久大香线蕉97| 国产精品久久久久天天影视| 91精品婷婷国产综合久久| 国产成人精品久久免费动漫| 中文字幕亚洲综合久久2| 一本大道久久香蕉成人网| 亚洲精品国精品久久99热一| 久久青草国产精品一区| 伊人久久大香线蕉综合5g| 久久er国产精品免费观看2| 亚洲欧美另类日本久久国产真实乱对白| 欧美久久综合九色综合| a级成人毛片久久| 久久久国产99久久国产一| 国产午夜福利精品久久2021 | 国产高潮国产高潮久久久| 合区精品久久久中文字幕一区| 久久亚洲AV成人无码电影| 亚洲欧洲久久av| 91久久精品国产成人久久| 久久久久人妻一区精品性色av | 99精品国产99久久久久久97 | 国产精品久久久久影院色| 区亚洲欧美一级久久精品亚洲精品成人网久久久久 | 99久久超碰中文字幕伊人| 久久国产AVJUST麻豆| 99久久国产综合精品成人影院| 亚洲国产精品成人久久| 久久99久国产麻精品66| 91麻豆国产精品91久久久| 青青热久久国产久精品 | 欧美精品久久久久久久自慰| 久久久久久久女国产乱让韩 | 久久精品无码专区免费青青| 欧美久久综合九色综合| 婷婷久久五月天| 久久久久久国产a免费观看黄色大片 | 久久丫精品国产亚洲av不卡| 久久天天躁狠狠躁夜夜2020一| 久久久久亚洲av成人网人人软件 | 少妇高潮惨叫久久久久久|