• <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>

            C++ Programmer's Cookbook

            {C++ 基礎} {C++ 高級} {C#界面,C++核心算法} {設計模式} {C#基礎}

            C++多線程(二)

            C/C++ Runtime 多線程函數

            一 簡單實例(來自codeprojct:http://www.codeproject.com/useritems/MultithreadingTutorial.asp
            主線程創建2個線程t1和t2,創建時2個線程就被掛起,后來調用ResumeThread恢復2個線程,是其開始執行,調用WaitForSingleObject等待2個線程執行完,然后推出主線程即結束進程。

            /*  file Main.cpp
             *
             *  This program is an adaptation of the code Rex Jaeschke showed in
             *  Listing 1 of his Oct 2005 C/C++ User's Journal article entitled
             *  "C++/CLI Threading: Part I".  I changed it from C++/CLI (managed)
             *  code to standard C++.
             *
             *  One hassle is the fact that C++ must employ a free (C) function
             *  or a static class member function as the thread entry function.
             *
             *  This program must be compiled with a multi-threaded C run-time
             *  (/MT for LIBCMT.LIB in a release build or /MTd for LIBCMTD.LIB
             *  in a debug build).
             *
             *                                      John Kopplin  7/2006
             
            */



            #include 
            <stdio.h>
            #include 
            <string>             // for STL string class
            #include <windows.h>          // for HANDLE
            #include <process.h>          // for _beginthread()

            using namespace std;


            class ThreadX
            {
            private:
              
            int loopStart;
              
            int loopEnd;
              
            int dispFrequency;

            public:
              
            string threadName;

              ThreadX( 
            int startValue, int endValue, int frequency )
              
            {
                loopStart 
            = startValue;
                loopEnd 
            = endValue;
                dispFrequency 
            = frequency;
              }


              
            // In C++ you must employ a free (C) function or a static
              
            // class member function as the thread entry-point-function.
              
            // Furthermore, _beginthreadex() demands that the thread
              
            // entry function signature take a single (void*) and returned
              
            // an unsigned.
              static unsigned __stdcall ThreadStaticEntryPoint(void * pThis)
              
            {
                  ThreadX 
            * pthX = (ThreadX*)pThis;   // the tricky cast
                  pthX->ThreadEntryPoint();           // now call the true entry-point-function

                  
            // A thread terminates automatically if it completes execution,
                  
            // or it can terminate itself with a call to _endthread().

                  
            return 1;          // the thread exit code
              }


              
            void ThreadEntryPoint()
              
            {
                 
            // This is the desired entry-point-function but to get
                 
            // here we have to use a 2 step procedure involving
                 
            // the ThreadStaticEntryPoint() function.

                
            for (int i = loopStart; i <= loopEnd; ++i)
                
            {
                  
            if (i % dispFrequency == 0)
                  
            {
                      printf( 
            "%s: i = %d\n", threadName.c_str(), i );
                  }

                }

                printf( 
            "%s thread terminating\n", threadName.c_str() );
              }

            }
            ;


            int main()
            {
                
            // All processes get a primary thread automatically. This primary
                
            // thread can generate additional threads.  In this program the
                
            // primary thread creates 2 additional threads and all 3 threads
                
            // then run simultaneously without any synchronization.  No data
                
            // is shared between the threads.

                
            // We instantiate an object of the ThreadX class. Next we will
                
            // create a thread and specify that the thread is to begin executing
                
            // the function ThreadEntryPoint() on object o1. Once started,
                
            // this thread will execute until that function terminates or
                
            // until the overall process terminates.

                ThreadX 
            * o1 = new ThreadX( 012000 );

                
            // When developing a multithreaded WIN32-based application with
                
            // Visual C++, you need to use the CRT thread functions to create
                
            // any threads that call CRT functions. Hence to create and terminate
                
            // threads, use _beginthreadex() and _endthreadex() instead of
                
            // the Win32 APIs CreateThread() and EndThread().

                
            // The multithread library LIBCMT.LIB includes the _beginthread()
                
            // and _endthread() functions. The _beginthread() function performs
                
            // initialization without which many C run-time functions will fail.
                
            // You must use _beginthread() instead of CreateThread() in C programs
                
            // built with LIBCMT.LIB if you intend to call C run-time functions.

                
            // Unlike the thread handle returned by _beginthread(), the thread handle
                
            // returned by _beginthreadex() can be used with the synchronization APIs.

                HANDLE   hth1;
                unsigned  uiThread1ID;

                hth1 
            = (HANDLE)_beginthreadex( NULL,         // security
                                               0,            // stack size
                                               ThreadX::ThreadStaticEntryPoint,
                                               o1,           
            // arg list
                                               CREATE_SUSPENDED,  // so we can later call ResumeThread()
                                               &uiThread1ID );

                
            if ( hth1 == 0 )
                    printf(
            "Failed to create thread 1\n");

                DWORD   dwExitCode;

                GetExitCodeThread( hth1, 
            &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
                printf( "initial thread 1 exit code = %u\n", dwExitCode );

                
            // The System::Threading::Thread object in C++/CLI has a "Name" property.
                
            // To create the equivalent functionality in C++ I added a public data member
                
            // named threadName.

                o1
            ->threadName = "t1";

                ThreadX 
            * o2 = new ThreadX( -100000002000 );

                HANDLE   hth2;
                unsigned  uiThread2ID;

                hth2 
            = (HANDLE)_beginthreadex( NULL,         // security
                                               0,            // stack size
                                               ThreadX::ThreadStaticEntryPoint,
                                               o2,           
            // arg list
                                               CREATE_SUSPENDED,  // so we can later call ResumeThread()
                                               &uiThread2ID );

                
            if ( hth2 == 0 )
                    printf(
            "Failed to create thread 2\n");

                GetExitCodeThread( hth2, 
            &dwExitCode );  // should be STILL_ACTIVE = 0x00000103 = 259
                printf( "initial thread 2 exit code = %u\n", dwExitCode );

                o2
            ->threadName = "t2";

                
            // If we hadn't specified CREATE_SUSPENDED in the call to _beginthreadex()
                
            // we wouldn't now need to call ResumeThread().

                ResumeThread( hth1 );   
            // serves the purpose of Jaeschke's t1->Start()

                ResumeThread( hth2 );

                
            // In C++/CLI the process continues until the last thread exits.
                
            // That is, the thread's have independent lifetimes. Hence
                
            // Jaeschke's original code was designed to show that the primary
                
            // thread could exit and not influence the other threads.

                
            // However in C++ the process terminates when the primary thread exits
                
            // and when the process terminates all its threads are then terminated.
                
            // Hence if you comment out the following waits, the non-primary
                
            // threads will never get a chance to run.

                WaitForSingleObject( hth1, INFINITE );
                WaitForSingleObject( hth2, INFINITE );

                GetExitCodeThread( hth1, 
            &dwExitCode );
                printf( 
            "thread 1 exited with code %u\n", dwExitCode );

                GetExitCodeThread( hth2, 
            &dwExitCode );
                printf( 
            "thread 2 exited with code %u\n", dwExitCode );

                
            // The handle returned by _beginthreadex() has to be closed
                
            // by the caller of _beginthreadex().

                CloseHandle( hth1 );
                CloseHandle( hth2 );

                delete o1;
                o1 
            = NULL;

                delete o2;
                o2 
            = NULL;

                printf(
            "Primary thread terminating.\n");
            }


            二解釋
            1)如果你正在編寫C/C++代碼,決不應該調用CreateThread。相反,應該使用VisualC++運行期庫函數_beginthreadex,推出也應該使用_endthreadex。如果不使用Microsoft的VisualC++編譯器,你的編譯器供應商有它自己的CreateThred替代函數。不管這個替代函數是什么,你都必須使用。

            2)因為_beginthreadex和_endthreadex是CRT線程函數,所以必須注意編譯選項runtimelibaray的選擇,使用MT或MTD。

            3) _beginthreadex函數的參數列表與CreateThread函數的參數列表是相同的,但是參數名和類型并不完全相同。這是因為Microsoft的C/C++運行期庫的開發小組認為,C/C++運行期函數不應該對Windows數據類型有任何依賴。_beginthreadex函數也像CreateThread那樣,返回新創建的線程的句柄。
            下面是關于_beginthreadex的一些要點:
            •每個線程均獲得由C/C++運行期庫的堆棧分配的自己的tiddata內存結構。(tiddata結構位于Mtdll.h文件中的VisualC++源代碼中)。

            •傳遞給_beginthreadex的線程函數的地址保存在tiddata內存塊中。傳遞給該函數的參數也保存在該數據塊中。

            •_beginthreadex確實從內部調用CreateThread,因為這是操作系統了解如何創建新線程的唯一方法。

            •當調用CreatetThread時,它被告知通過調用_threadstartex而不是pfnStartAddr來啟動執行新線程。還有,傳遞給線程函數的參數是tiddata結構而不是pvParam的地址。

            •如果一切順利,就會像CreateThread那樣返回線程句柄。如果任何操作失敗了,便返回NULL。

            4) _endthreadex的一些要點:
            •C運行期庫的_getptd函數內部調用操作系統的TlsGetValue函數,該函數負責檢索調用線程的tiddata內存塊的地址。

            •然后該數據塊被釋放,而操作系統的ExitThread函數被調用,以便真正撤消該線程。當然,退出代碼要正確地設置和傳遞。

            5)雖然也提供了簡化版的的_beginthread和_endthread,但是可控制性太差,所以一般不使用。

            6)線程handle因為是內核對象,所以需要在最后closehandle。

            7)更多的API:HANDLE GetCurrentProcess();HANDLE GetCurrentThread();DWORD GetCurrentProcessId();DWORD GetCurrentThreadId()。DWORD SetThreadIdealProcessor(HANDLE hThread,DWORD dwIdealProcessor);BOOL SetThreadPriority(HANDLE hThread,int nPriority);BOOL SetPriorityClass(GetCurrentProcess(),  IDLE_PRIORITY_CLASS);BOOL GetThreadContext(HANDLE hThread,PCONTEXT pContext);BOOL SwitchToThread();

            三注意
            1)C++主線程的終止,同時也會終止所有主線程創建的子線程,不管子線程有沒有執行完畢。所以上面的代碼中如果不調用WaitForSingleObject,則2個子線程t1和t2可能并沒有執行完畢或根本沒有執行。
            2)如果某線程掛起,然后有調用WaitForSingleObject等待該線程,就會導致死鎖。所以上面的代碼如果不調用resumethread,則會死鎖。

            posted on 2007-07-25 13:25 夢在天涯 閱讀(28239) 評論(1)  編輯 收藏 引用 所屬分類: CPlusPlus

            評論

            # re: C++多線程(二) 2007-07-25 14:43 pass86

            關注  回復  更多評論   

            公告

            EMail:itech001#126.com

            導航

            統計

            • 隨筆 - 461
            • 文章 - 4
            • 評論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1808261
            • 排名 - 5

            最新評論

            閱讀排行榜

            国产亚洲欧美成人久久片| 国产激情久久久久影院老熟女免费 | 久久久免费观成人影院| 久久久久国产成人精品亚洲午夜| 国产精品欧美亚洲韩国日本久久| 久久露脸国产精品| 久久精品国产网红主播| 精品无码久久久久久久动漫| 精品久久久无码人妻中文字幕| 99精品国产在热久久无毒不卡| 久久精品免费大片国产大片| 青青草原精品99久久精品66| 久久国产V一级毛多内射| 亚洲综合熟女久久久30p| 久久久久九九精品影院| 精品久久久久久久无码| 久久只有这里有精品4| 国内精品久久久久久久影视麻豆| 欧美日韩精品久久久久| 伊人久久精品线影院| 久久久噜噜噜久久中文福利| 亚洲午夜久久久| 久久免费99精品国产自在现线| 久久91精品国产91久久户| 亚洲精品无码久久久久久| 一本久久精品一区二区| 久久久久无码精品| AA级片免费看视频久久| 欧美久久精品一级c片片| 精品久久久久久中文字幕| 久久久久无码精品国产| 久久免费看黄a级毛片| 2019久久久高清456| 亚洲精品NV久久久久久久久久| 国产精品九九久久精品女同亚洲欧美日韩综合区 | 精品久久久久久无码专区| 久久久久久久女国产乱让韩| 亚洲综合久久夜AV | 色婷婷久久久SWAG精品| 亚洲人AV永久一区二区三区久久| 久久免费99精品国产自在现线|