C++多執行緒例項(_beginThreadex建立多執行緒)
C++多執行緒(二)(_beginThreadex建立多執行緒)
C/C++ Runtime 多執行緒函式
一 簡單例項(來自codeprojct:http://www.codeproject.com/useritems/MultithreadingTutorial.asp)
主執行緒建立2個執行緒t1和t2,建立時2個執行緒就被掛起,後來呼叫ResumeThread恢復2個執行緒,是其開始執行,呼叫WaitForSingleObject等待2個執行緒執行完,然後推出主執行緒即結束程序。
*
* This program is an adaptation of the code Rex Jaeschke showed in
* "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
* 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
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().
return1; // 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( 0, 1, 2000 );
// 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( -1000000, 0, 2000 );
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 );
//WaitForSingleObject函式用來檢測 hHandle 事件的訊號狀態,當函式的執行時間超過 dwMilliseconds 就返回,
//但如果引數 dwMilliseconds 為 INFINITE 時函式將直到相應時間事件變成有訊號狀態才返回,否則就一直等待下去
//,直到 WaitForSingleObject有返回直才執行後面的程式碼
GetExitCodeThread( hth1, &dwExitCode );
printf( "thread 1 exited with code %u\n", dwExitCode );
GetExitCodeThread( hth2, &dwExitCode );
printf( "thread 2 exited with code %u\n", dwExitCode );
//
//GetExitCodeThread這個函式是獲得執行緒的退出碼, 第二個引數是一個 DWORD的指標,
//使用者應該使用一個 DWORD 型別的變數去接收資料,返回的資料是執行緒的退出碼,
//第一個引數是執行緒控制代碼,用 CreateThread 建立執行緒時獲得到。
//通過執行緒退出碼可以判斷執行緒是否正在執行,還是已經退出。
// 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的一些要點:
&8226;每個執行緒均獲得由C/C++執行期庫的堆疊分配的自己的tiddata記憶體結構。(tiddata結構位於Mtdll.h檔案中的VisualC++原始碼中)。
&8226;傳遞給_beginthreadex的執行緒函式的地址儲存在tiddata記憶體塊中。傳遞給該函式的引數也儲存在該資料塊中。
&8226;_beginthreadex確實從內部呼叫CreateThread,因為這是作業系統瞭解如何建立新執行緒的唯一方法。
&8226;當呼叫CreatetThread時,它被告知通過呼叫_threadstartex而不是pfnStartAddr來啟動執行新執行緒。還有,傳遞給執行緒函式的引數是tiddata結構而不是pvParam的地址。
&8226;如果一切順利,就會像CreateThread那樣返回執行緒控制代碼。如果任何操作失敗了,便返回NULL。
4) _endthreadex的一些要點:
&8226;C執行期庫的_getptd函式內部呼叫作業系統的TlsGetValue函式,該函式負責檢索呼叫執行緒的tiddata記憶體塊的地址。
&8226;然後該資料塊被釋放,而作業系統的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,則會死鎖。
來源自自1999年7月MSJ雜誌的《Win32 Q&A》欄目
你也許會說我一直用CreateThread來建立執行緒,一直都工作得好好的,為什麼要用_beginthreadex來代替CreateThread,下面讓我來告訴你為什麼。
回答一個問題可以有兩種方式,一種是簡單的,一種是複雜的。
如果你不願意看下面的長篇大論,那我可以告訴你簡單的答案:_beginthreadex在內部呼叫了CreateThread,在呼叫之前_beginthreadex做了很多的工作,從而使得它比CreateThread更安全。
相關推薦
C++多執行緒例項(_beginThreadex建立多執行緒)
C++多執行緒(二)(_beginThreadex建立多執行緒) C/C++ Runtime 多執行緒函式 一 簡單例項(來自codeprojct:http://www.codeproject.com/useritems/MultithreadingTutorial.asp) 主執行緒建立2個執行緒t1
python多執行緒———2、建立多執行緒的兩種方式
法一、使用Thread類例項化 法二、繼承Thread來實現多執行緒 #對於io操作來說,多執行緒和多程序效能差別不大 #1、使用Thread類例項化 import time import threading def get_detail_html(url): prin
Qt多執行緒學習:建立多執行緒
【為什麼要用多執行緒?】 傳統的圖形使用者介面應用程式都只有一個執行執行緒,並且一次只執行一個操作。如果使用者從使用者介面中呼叫一個比較耗時的操作,當該操作正在執行時,使用者介面通常會凍結而不再響應。這個問題可以用事件處理和多執行緒來解決。 【Linux有執行緒的概念嗎?
一個php腳本執行中實例多次PDO,會建立多次數據庫連接。
重用 slist OS play 類實例化 每次 連接 inf log 腳本代碼: <?php try { $dbh = new PDO(‘mysql:host=localhost;dbname=test‘, ‘root‘, ‘root‘); } ca
C++11的執行緒類,建立的執行緒,如何設定優先順序?
SetThreadPriorityThe SetThreadPriority function sets the priority value for the specified thread. This value, together with the priority
tensorflow例項(7)--建立多層神經網路
本文將建立多層神經網路的函式,這個函式是一個簡單的通用函式,通過最後的測試,可以建立一些多次方程的模型,並通過matplotlib.pyplot演示模型建立過程中的資料變化情況以下三張圖片是生成的效果,每張圖的藍點都表示為樣本值,紅點表示最終預測效果,本例帶有點動畫效果,可以
一個MySql例項自動建立多個Activiti資料庫問題
一次使用SSH和Activiti6開發的專案中,在伺服器啟動的時候就報錯:org.apache.ibatis.exceptions.PersistenceException: ### Error querying database. Cause: java.sql.SQLS
IDEA+Maven+多個Module模組(建立多模組SpringBoot整合專案)
最近在學習springboot,先從建立專案開始,一般專案都是一個專案下會有多個模組,這裡先建立一個最簡單的例項,一個專案下有一個springboot模組專案提供web服務,引用另一個java專案(相當於業務邏輯) 期望的專案結構如下 springboot-test —
JBPM4入門——6.流程例項的建立和執行
package com.test.test; import java.util.Iterator; import java.util.List; import org.jbpm.api.ProcessDefinition; import org.jbpm.api.ProcessDefinitionQuer
C++多執行緒例項(執行緒的建立—排程—正確結束)
C++中的多執行緒程式設計時一個非常複雜的東西,使用過程中一定要注意執行緒的排程和結束。那麼為什麼要用多執行緒呢?舉一個例子,介面裡有個按鈕,按鈕按下後,這個操作需要非常長的時間才能完成,那麼在操作未完成之前,會將介面卡死,無法進行其他操作,這就是需要多執行緒的原因,一個主
c++多執行緒例項
主要總結了基於C++的多執行緒函式CreateThread,互斥鎖(或者稱資源獨佔)函式CreateMutex,等待資源函式WaitForSingleObject,關閉執行緒函式(其實是關閉執行緒的控制代碼)CloseHanlde,釋放互斥鎖函式ReleaseMutex的
ndk多執行緒需要獲取JNIEnv 或c通過類名+包名建立物件使用如下方法
JavaVM* mJavaVM; static pthread_key_t mThreadKey; static void Android_JNI_ThreadDestroyed(void* value) { JNIEnv *env = (JNIEnv*)
多執行緒程式設計之建立執行緒(Windows下C++實現)
執行緒概述 理解Windows核心物件 執行緒是系統核心物件之一。在學習執行緒之前,應先了解一下核心物件。核心物件是系統核心分配的一個記憶體塊,該記憶體塊描述的是一個數據結構,其成員負責維護物件的各種資訊。核心物件的資料只能由系統核心來訪問,應用程式無法在記
C++之多執行緒(POSIX多執行緒例項)
1.程序同時建立5個執行緒,各自呼叫同一個函式 #include <iostream> #include <pthread.h> //多執行緒相關操作標頭檔案,可移植眾多平臺 using namespace std; #define NUM_TH
多執行緒第一篇:使用_beginthreadex建立執行緒
我們先來了解一下執行緒的相關函式:CreateThread函式:HANDLE WINAPI CreateThread ( _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes , // pointer to security attributes _I
C語言多執行緒例項之pthread的應用(在windows下的應用(win7))
Pthread是由POSIX提出的一套通用的執行緒庫,在linux平臺下,它被廣泛的支援,而windows平臺下,卻並不被支援,而pthreads-w32為我們提供瞭解決方案,本文我們準備在我們的windows平臺下進行pthread-w32的安裝,在網路上有類
在linux c++類中的成員函式裡建立多執行緒要注意的地方
如何在linux 下c++中類的成員函式中建立多執行緒 linux系統中執行緒程式庫是POSIX pthread。POSIX pthread它是一個c的庫,用C語言進行多執行緒程式設計我這裡就不多說了,網上的例子很多。但是如何在C++的類中實現多執行緒程式設計呢?如果套
Objecttive-C 建立多執行緒
在Objecttive-C裡建立多執行緒一般有兩種方法, 一種是initWithTarget,還有一種是detachNewThreadSelector。 下面是兩個例項,建立多執行緒的例項,支援傳遞引數. initWithTarget方式 // // main.m /
C++多執行緒例項之臨界區同步
本篇是對上一篇 進行了重構,增加了windos下的臨界區鎖。 臨界區的特點:非核心物件,只能在window下使用,linux下不能使用;只能在同一程序內的執行緒間使用,速度快。 互斥量特點:互斥量是核心物件,可以用於程序內也可以在程序間互斥,速度相對互斥量慢點,也可以
Objective-C高階程式設計:iOS與OS X多執行緒和記憶體管理
這篇文章主要給大家講解一下GCD的平時不太常用的API,以及文末會貼出GCD定時器的一個小例子。 需要學習的朋友可以通過網盤免費下載pdf版 (先點選普通下載-----再選擇普通使用者就能免費下載了)http://putpan.com/fs/cy1i1beebn7s0h4u9/ 1.G