国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
線程的使用
線程的使用

1.創(chuàng)建簡單的線程;
在視圖類的鼠標的消息映射函數(shù)中加入:
    AfxBeginThread((AFX_THREADPROC)TestThread,this);
然后在視圖類中加入線程的入口函數(shù):
UINT TestThread(LPVOID pParam)
{
    AfxMessageBox("這是一個測試工作線程的對話框");
    return 0;
}
函數(shù)說明:
CWinThread* AfxBeginThread( AFX_THREADPROC pfnThreadProc, LPVOID pParam, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
CWinThread* AfxBeginThread( CRuntimeClass* pThreadClass, int nPriority = THREAD_PRIORITY_NORMAL, UINT nStackSize = 0, DWORD dwCreateFlags = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );
PfnThreadProc:
    指向工作者線程的控制函數(shù),不能是NULL,函數(shù)的定義必須如下:
UINT MyControllingFunction( LPVOID pParam );
PThreadClass:CwinThread的RUNTIME_CLASS對象.
PParam:傳遞給控制函數(shù)的參數(shù).
Npriority:線程的優(yōu)先級,可以用函數(shù)
BOOL SetThreadPriority(
  HANDLE hThread, // handle to the thread
  int nPriority   // thread priority level
);來設定
nStackSize:堆棧的大小,如果為0,就和創(chuàng)建的主線程一樣的大小.
DwCreateFlags:創(chuàng)建線程時的附加標志,可以為CREATE_SUSPENDED,代表掛起線程,直到調(diào)用DWORD ResumeThread( );函數(shù)時才執(zhí)行,為0,表示立即執(zhí)行.
LpSecurityAttrs:指向一個SECURITY_ATTRIBUTES描述線程的安全性,如果與主線程一樣的安全屬性,可以為NULL.
另外可以用CwinThread類的成員函數(shù)
BOOL CreateThread( DWORD dwCreateFlags = 0, UINT nStackSize = 0, LPSECURITY_ATTRIBUTES lpSecurityAttrs = NULL );來創(chuàng)建一個線程,具體的參數(shù)和上面一樣.
還可以用API來創(chuàng)建線程:
HANDLE CreateThread(
  LPSECURITY_ATTRIBUTES lpThreadAttributes,  // pointer to security attributes
  DWORD dwStackSize,                         // initial thread stack size
  LPTHREAD_START_ROUTINE lpStartAddress,     // pointer to thread function
  LPVOID lpParameter,                        // argument for new thread
  DWORD dwCreationFlags,                     // creation flags
  LPDWORD lpThreadId                         // pointer to receive thread ID
);
DWORD WINAPI YourThreadFunc(LPVOIDlpvThreadParm);
lpThreadId:32位標示符,用來接收線程的標示
函數(shù)返回的都是創(chuàng)建線程的句柄.
2.如何結(jié)束一個線程:
void AfxEndThread( UINT nExitCode );//結(jié)束當前正在運行的線程.
NExitCode:為線程退出代碼.
BOOL TerminateThread(
  HANDLE hThread,    // handle to the thread
  DWORD dwExitCode   // exit code for the thread
);
如果線程調(diào)用了VOID ExitThread(UINTfuExitCode);也可以終止

3.如何取得線程的退出代碼;
使用函數(shù)
BOOL GetExitCodeThread(
  HANDLE hThread,      // handle to the thread
  LPDWORD lpExitCode   // address to receive termination status
);
4.設置線程的優(yōu)先級;
BOOL SetThreadPriority(
  HANDLE hThread, // handle to the thread
  int nPriority   // thread priority level
);
nPriority;線程的優(yōu)先級,有:THREAD_PRIORITY_ABOVE_NORMAL,THREAD_PRIORITY_BELOW_NORMAL,THREAD_PRIORITY_HIGHEST,THREAD_PRIORITY_IDLE,THREAD_PRIORITY_LOWEST,THREAD_PRIORITY_NORMAL,THREAD_PRIORITY_TIME_CRITICAL具體的函數(shù)參見MSDN。
在上面創(chuàng)建的工作者線程中我們可以這樣設置優(yōu)先級:
    SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_HIGHEST);//設置比通常高兩個點
5.如何創(chuàng)建多線程多任務。
可以調(diào)用利用上面的線程創(chuàng)建函數(shù),傳遞給同一個線程函數(shù)不同的參數(shù),也可以開始另外一個線程。
6.掛起和恢復線程:
先前我提到過可以創(chuàng)建掛起狀態(tài)的線程(通過傳遞CREATE_SUSPENDED標志給函數(shù)CreateThread來實現(xiàn))。當你這樣做時,系統(tǒng)創(chuàng)建指定線程的核心對象,創(chuàng)建線程的棧,在CONTEXT結(jié)構中初始化線程CPU注冊成員。然而,線程對象被分配了一個初始掛起計數(shù)值1,這表明了系統(tǒng)將不再分配CPU去執(zhí)行線程。要開始執(zhí)行一個線程,一個線程必須調(diào)用ResumeThread并傳遞給它調(diào)用CreateThread時返回的線程句柄。
DWORD ResumeThread(HANDLE hThread);
一個線程可以被掛起多次。如果一個線程被掛起3次,則該線程在它被分配CPU之前必須被恢復3次。除了在創(chuàng)建線程時使用CREATE_SUSPENDED標志,你還可以用SuspendThread函數(shù)掛起線程。
DWORDSuspendThread(HANDLE hThread);
7.線程同步對象的使用;
同步對象有:Critical_section(臨界區(qū)),Event(事件),Mutex(互斥對象),Semaphores(信號量)。都有相應的API創(chuàng)建函數(shù)和MFC類,同步對象可以處于兩種狀態(tài):信號狀態(tài)(signal state)或非信號狀態(tài),當一個線程與某個對象相關聯(lián)時,若該對象處于非信號狀態(tài),則要等到其變成信號狀態(tài)線程才能繼續(xù)執(zhí)行。
WIN32 API提供了等待命令WaitForSingleObject和WaitForMutipleObjects:
  DWORD WaitForSingleObject(
                HANDLE hObject,                         // 要等待的對象句柄
                DWORD dwMilliseconds);  // 最大等待時間(毫秒)
        DWORD WaitforMultipleObjects(
                DWORD dwNumObjects,             // 要等待的對象數(shù)
                LPHANDLE lpHandles,             // 對象句柄數(shù)組
                BOOL bWaitAll,               // 是否等待所有對象都有信號才返回
                DWORD dwMilliseconds);  // 最大等待時間
如果在指定時間內(nèi)對象達到 信號狀態(tài)則返回WAIT_OBJECT_0,超時返回WAIT_TIMEOUT,出錯返回 WAIT_FAILED。對于互斥量、信號量和自動重置(auto-reset)事件對象,等待成功 時將它們改成非信號狀態(tài)(信號量計數(shù)器減1),以實現(xiàn)對象的互斥訪問。
件:jianuangzhiganhue
8.事件:
“事件”——一個允許一個事件發(fā)生時線程通知另一個線程的同步對象。在一個線程需要了解何時執(zhí)行任務時,事件是十分有用的。
CEvent對象有兩種類型:自動和手工。一個手工CEvent對象存在于由ResetEvent 或SetEvent設置的狀態(tài)中,直到另一個函數(shù)被調(diào)用。一個自動CEvent對象在至少一個線程被釋放后自動返回一個無標記(無用的)狀態(tài)。
CEvent( BOOL bInitiallyOwn = FALSE, BOOL bManualReset = FALSE, LPCTSTR lpszName = NULL, LPSECURITY_ATTRIBUTES lpsaAttribute = NULL );
BInitiallyOwn;如果為TRUE, CMultilock or CsingleLock對象就可以使用,為FALSE,線程就必須等到直到所需的資源被釋放.
BManualReset:為TRUE,設置為手動復位事件對象,為FALSE,設置為自動復位事件對象.
LpszName:事件對象的名稱,不能指定一個已經(jīng)存在的對象
LpsaAttribute:事件對象的安全屬性
與同步對象相關的多個同步訪問對象CMultilock 和單個同步訪問對象 CsingleLock對象.
CSingleLock( CSyncObject* pObject, BOOL bInitialLock = FALSE );
PObject:指向一個要處理的同步對象
BinitialLock:指定是否初始的時候就嘗試訪問對象。
CMultiLock( CSyncObject* ppObjects[ ], DWORD dwCount, BOOL bInitialLock = FALSE );
DwCount:指定同步對象的個數(shù),必須大于0。
下面簡單介紹他們的應用:
調(diào)用此成員函數(shù)構造一個已命名或未命名的CEvent對象。要訪問或釋放一個CEvent對象,可建立一個CSingleLock或CMultiLock對象并調(diào)用其Lock和Unlock成員函數(shù)。要將CEvent對象的狀態(tài)改為已標記(無須等待的線程),可調(diào)用SetEvent或PulseEvent。要設置一個CEvent對象為無標記(必須等待的線程),可調(diào)用ResetEvent。
可以在你的線程開始設置CEvent::SetEvent,其他線程使用CSingleLock::Lock來等待你線程處理結(jié)束。當你的線程處理完畢,使用CEvent::ResetEvent清除事件,其他程序就可以繼續(xù)執(zhí)行了。
API函數(shù):
    HANDLE CreateEvent(
                LPSECURITY_ATTRIBUTES lpsa,     // 安全屬性指針,Win98忽略
                BOOL bManualRest,              // 是否手動重置(manual-reset)
                BOOL bInitialState,            // 初始狀態(tài)是否為信號狀態(tài)
                LPCTSTR lpName);              // 對象名字符串指針
自動重置(auto-reset)事件和手動重置(manual-reset)事件,這由CreateEvent()的第二個參數(shù)指定。對于自動重置事件,WaitForSingleObject()和 WaitForMultipleObjects()會等待事件到信號狀態(tài),隨后又自動將其重置為非信號狀 態(tài),這樣保證了等待此事件的線程中只有一個會被喚醒。而手動重置事件需要用戶調(diào)用ResetEvent()才會重置事件??赡苡腥舾蓚€線程在等待同一事件,這樣當事件變 為信號狀態(tài)時,所有等待線程都可以運行了。 SetEvent()函數(shù)用來把事件對象設置成信號狀態(tài),ResetEvent()把事件對象重置成非信號狀態(tài),兩者均需事件對象句柄作參數(shù)。
9.臨界區(qū)
同一時刻只允許一個線程存取資源或代碼區(qū)。臨界區(qū)在控制一次只有一個線程修改數(shù)據(jù)或其它的控制資源時非常有用。在運行性能比較重要而且資源不會跨進程使用時,建議采用臨界區(qū)代替信號燈。有關在MFC中使用信號燈的詳細信息,請參閱CMutex。使用CCriticalSection對象之前,需要構造它。在構造函數(shù)返回后,就可以使用臨界區(qū)了。在使用完之后要調(diào)用UnLock函數(shù)。存取由CCriticalSection控制的資源時,要在資源的存取函數(shù)中定義一個CSingleLock型的變量。然后調(diào)用加鎖對象的Lock成員函數(shù)(如CSingleLock::Lock)。此時,調(diào)用的線程要么獲得對資源的存取權,要么等待他人釋放資源等待加鎖,或者等待他人釋放資源,但又因為超時而加鎖失敗。這樣就保證了一次只有一個線程在存取臨界資源。釋放資源只需調(diào)用成員函數(shù)UnLock(例如CSingleLock:Unlock),或讓鎖對象在作用范圍之外。
此外,可以單獨地建立一個CCriticalSection對象,并在存取臨界資源之前顯式地存取它。這種方式有助于保持代碼的清晰,但是更容易出錯,因為要記住在存取臨界資源前加鎖,存取之后開鎖。
構造函數(shù):CCriticalSection ( );
成員函數(shù):BOOL Lock( ); BOOL Lock( DWORD dwTimeout ); 本函數(shù)用于取得對臨界區(qū)對象的存取權。Lock是一個成塊性的操作,直到取得臨界區(qū)對象的存取權才返回。
virtual BOOL UnLock( ); 如果臨界區(qū)是被本線程占用的并且開鎖成功,則返回非零值。否則為0。本函數(shù)釋放線程占用的CCriticalSection對象。如果CCriticalSection是單獨使用的,在獨占使用完臨界資源以后,應盡快調(diào)用UnLock開鎖。如果使用了CSingleLock對象,CCriticalSection::Unlock將會在它的成員函數(shù)Unlock中調(diào)用。
API函數(shù):
CRITICAL_SECTION cs; 然后初始化,調(diào)用下面函數(shù)(參數(shù)為空對象的指針):
     VOID InitializeCriticalSection(LPCRITICAL_SECTION lpcs);
     VOID EnterCriticalSection(LPCRITICAL_SECTION lpcs); 進入和離開臨界區(qū)分別調(diào)用函數(shù):
     VOID LeaveCriticalSection(LPCRITICAL_SECTION lpcs);
     VOID DeleteCriticalSection(LPCRITICAL_SECTION lpcs); 刪除臨界區(qū)對象用:
10. Mutex(互斥對象)
它為一個同步對象,允許某線程共同訪問同一資源。在僅僅一個線程被允許用于修改數(shù)據(jù)或其它被控制的資源時。
一種使用CMutex 對象的方法就是一個CMutex類型的變量,將其作為你希望控制類的數(shù)據(jù)成員。在被控制對象的構造過程中,若互斥對象最初擁有了互斥對象的名稱或期待的安全屬性,那么就調(diào)用CMutex數(shù)據(jù)成員指定的構造函數(shù),以這種方式訪問由CMutex 對象控制的資源,首先要在資源訪問的成員函數(shù)中創(chuàng)建CSingleLock類型或CMultiLock類型的變量。然后調(diào)用封鎖對象的Lock成員函數(shù)(例如, CSingleLock::Lock)。這樣,你的線程要么就獲得資源的訪問權,以等待將要釋放的資源,并獲取訪問權,要么就等待將要釋放的資源,當超時后,返回失敗。在任何一種情況下,都可以在線程安全的模式下訪問資源。若要釋放這些資源,使用封鎖對象的Unlock成員函數(shù)(例如, CSingleLock::Unlock),或允許封鎖對象越界。
CMutex( BOOL bInitiallyOwn = FALSE, LPCTSTR lpszName = NULL,LPSECUR-ITY_ATTRIBUTES lpsaAttribute = NULL );
BInitiallyOwn:指定是否創(chuàng)建了CMutex 對象的線程最初擁有由互斥對象控制資源的訪問權。
lpszName:CMutex 對象的名稱。若其它的互斥對象由同樣的名稱,那么必須提供lpszName,以便對象能夠通過進程邊界。若該值為NULL,那么互斥對象將沒有命名。若該名稱匹配已經(jīng)存在的互斥對象,那么構造函數(shù)將創(chuàng)建一個參考互斥對象名稱的新CMutex 對象。若該名稱匹配已存在的不是互斥對象的同步對象,那么構造過程將失敗。
LpsaAttribute:對象的安全性
API函數(shù):

HANDLE CreateMutex(
                LPSECURITY_ATTRIBUTES lpsa,     // 安全屬性指針
                BOOL bInitialOwner,             // TR UE表示線程將擁有該信號量
                LPCTSTR lpName);                // 對象名
在別的進程中可以用相同的互斥量名調(diào)用CreateMutex()和 OpenMutex()來打開該對象,這樣互斥量就可用于多個進程中,線程通過WaitForSingleObject()和WaitForMultipleObject()來等待一個互斥量,用ReleaseMutex()來釋放一個互斥量。
11.Semaphores(信號量)
    一個CSemaphore類對象代表一個“信號”一個同步對象,它允許有限數(shù)目的線程在一個或多個進程中訪問同一個資源。一個Semaphore對象保持了對當前訪問某一指定資源的線程的計數(shù)。
對于一個只能支持有限數(shù)目用戶的共享資源來說,CSemaphore是很有用的。
CSemaphore對象的當前計數(shù)是還可以允許的其它用戶的數(shù)目。當這個計數(shù)達到零的時候,所有對這個由CSemaphore對象控制的資源的訪問嘗試都將被插入到一個系統(tǒng)隊列中等待,直到它們的時間用完或計數(shù)值不再為零。這個被控制的資源可以同時接受訪問的最大用戶數(shù)目是在CSemaphore對象的構造期間被指定的。
使用CSemaphore對象的另一種方法是,將一個CSemaphore類型的變量添加到你想要控制的類中作為一個數(shù)據(jù)成員。在被控制對象的構造期間,調(diào)用CSemaphore數(shù)據(jù)成員的構造函數(shù)來指定訪問計數(shù)的初始值,訪問計數(shù)的最大值,信號的名字(如果它要在整個進程中使用),以及需要的安全標志。要訪問由CSemaphore對象用這種方式控制的資源,首先要在你的資源的訪問成員函數(shù)中創(chuàng)建一個CSingleLock類型或CMultiLock類型的變量。然后調(diào)用加鎖對象的Lock成員函數(shù)(例如,CSingleLock::Lock)。這時,你的線程將達到對資源的訪問,等待資源被釋放并訪問它,或者是在等待資源被釋放的過程中超過了時間,對資源的訪問失敗。不管是哪一種情況,你的資源都是以一種線程安全(thread-safe)方式被訪問的。要釋放資源,可以使用加鎖對象的Unlock成員函數(shù)(例如,CSingleLock::Unlock),或者是讓加鎖對象超越范圍。
CSemaphore( LONG lInitialCount = 1, LONG lMaxCount = 1, LPCTSTR pstrName= NULL,       LPSECURITY_ATTRIBUTES lpsaAttributes = NULL );
LInitialCount:信號的初始使用計數(shù)。必須是大于或等于0,并且小于或等于lMaxCount。
LMaxCount:信號的使用計數(shù)的最大值。必須大于0。
PstrName:信號的名字。如果此信號將在整個進程中被訪問,則必須提供這個名字。如果是NULL,則對象將是沒有名字的。如果這個名字與一個已經(jīng)存在的信號的名字一樣,則構造函數(shù)創(chuàng)建一個新的CSemaphore對象,此對象引用具有這個名字的對象。如果這個名字與一個已經(jīng)存在的但不是一個信號的同步對象的名字一樣,則構造函數(shù)會失敗。
API使用:
HANDLE CreateSemaphore(
                LPSECURITY_ATTRIBUTES lpSecAttr,        // 安全屬性指針
                LONG InitialCoutn,                       // 初始信號量數(shù)目
                LONG lMaxCount,                        // 允許的最大信號量數(shù)目
                LPCTSTR lpszSemName);                 // 信號量對象名指針
當信號量數(shù)目大于0時,就處于信號狀態(tài)。若lpszSemName參數(shù)為NULL時,信號量局限于一個進程的線程中;若給予一個字符串對象名,則其它進程也可以使 用該信號量。別的進程中可以在調(diào)用CreateSemaphore()和OpenSemaphore()時把這個字符串名作參數(shù),以打開該信號量,這樣可以實現(xiàn)多個進程間的同步。WaitForSingleObject()和WaitForMultipleObjects()來等待一個信號量。當完成同步任務時,線程應用ReleaseSemaphore()來釋放信號量:
BOOL ReleaseSemaphore(HANDLE hSema, LONG lReleaseCount, LPLONG  lpPrevious);
12.用戶界面線程的創(chuàng)建:
創(chuàng)建用戶界面線程時,必須首先從 CWinThread 派生類。必須使用 DECLARE_DYNCREATE 和 IMPLEMENT_DYNCREAT宏聲明并實現(xiàn)此類。用戶界面線程通常用于處理用戶輸入和響應用戶事件。
13.進程的創(chuàng)建和終止;
調(diào)用CreateProcess函數(shù)創(chuàng)建新的進程,運行指定的程序。CreateProcess的原型如下:
BOOL CreateProcess(
LPCTSTR lpApplicationName,
LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
其中:
lpApplicationName指向包含了要運行模塊名字的字符串。
lpCommandLine指向命令行字符串。
lpProcessAttributes描述進程的安全性屬性,NT下有用。
lpThreadAttributes描述進程初始線程(主線程)的安全性屬性,NT下有用。
bInHeritHandles表示子進程(被創(chuàng)建的進程)是否可以繼承父進程的句柄??梢岳^承的句柄有線程句柄、有名或無名管道、互斥對象、事件、信號量、映像文件、普通文件和通訊端口等;還有一些句柄不能被繼承,如內(nèi)存句柄、DLL實例句柄、GDI句柄、URER句柄等等。
子進程繼承的句柄由父進程通過命令行方式或者進程間通訊(IPC)方式由父進程傳遞給它。
dwCreationFlags表示創(chuàng)建進程的優(yōu)先級類別和進程的類型。創(chuàng)建進程的類型分控制臺進程、調(diào)試進程等;優(yōu)先級類別用來控制進程的優(yōu)先級別,分Idle、Normal、High、Real_time四個類別。
lpEnviroment指向環(huán)境變量塊,環(huán)境變量可以被子進程繼承。
lpCurrentDirectory指向表示當前目錄的字符串,當前目錄可以繼承。
lpStartupInfo指向StartupInfo結(jié)構,控制進程的主窗口的出現(xiàn)方式。
lpProcessInformation指向PROCESS_INFORMATION結(jié)構,用來存儲返回的進程信息。
從其參數(shù)可以看出創(chuàng)建一個新的進程需要指定什么信息。
從上面的解釋可以看出,一個進程包含了很多信息。若進程創(chuàng)建成功的話,返回一個進程信息結(jié)構類型的指針。進程信息結(jié)構如下:
typedef struct _PROCESS_INFORMATION {
HANDLE hProcess;
HANDLE hThread;
DWORD dwProcessId;
DWORD dwThreadId;
}PROCESS_INFORMATION;
進程信息結(jié)構包括進程句柄,主線程句柄,進程ID,主線程ID。
進程的終止
進程在以下情況下終止:
調(diào)用ExitProcess結(jié)束進程;
進程的主線程返回,隱含地調(diào)用ExitProcess導致進程結(jié)束;
進程的最后一個線程終止;
調(diào)用TerminateProcess終止進程。
當要結(jié)束一個進程時,發(fā)送WM_QUIT消息給主窗口,當然也可以從它的任一線程調(diào)用ExitProcess。
本站僅提供存儲服務,所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
同步
多線程學習筆記
第八章 MFC的進程和線程
多線程與串行通信
線程的基礎知識
VC 中進程與多進程管理的方法
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服