1、線程函數聲明
DWORD WINAPI ThreadProc( LPVOID lpParameter);
2、創建線程函數
HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId);
lpThreadAttributes:它被設爲NULL,表示使用缺省值。
dwStackSize,線程堆棧大小,一般=0,在任何情況下,
Windows根據需要動態延長堆棧的大小。
lpStartAddress,指向線程函數的指針,
形式:@函數名,函數名稱沒有限制,
但是必須以下列形式聲明: DWORD WINAPI ThreadProc (LPVOID pParam) ,
格式不正確將無法調用成功。
lpParameter:向線程函數傳遞的參數,是一個指向結構的指針,
不需傳遞參數時,爲NULL。
dwCreationFlags :線程標誌,可取值如下
CREATE_SUSPENDED: 創建一個掛起的線程
0 :創建後立即激活。 lpThreadId:保存新線程的id。
返回值: 函數成功,返回線程句柄;函數失敗返回false。
4、WaitForSingleObject函數
DWORD WaitForSingleObject(
HANDLE hHandle,
DWORD dwMilliseconds
);
參數
hHandle 對象句柄。可以指定一系列的對象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。
當等待仍在掛起狀態時,句柄被關閉,那麼函數行爲是未定義的。該句柄必須具有 SYNCHRONIZE 訪問權限。
dwMilliseconds [in]定時時間間隔,單位爲milliseconds(毫秒).如果指定一個非零值,函數處於等待狀態直到hHandle 標記的對象被觸發,或者時間到了。如果dwMilliseconds 爲0,對象沒有被觸發信號,函數不會進入一個等待狀態,它總是立即返回。如果dwMilliseconds 爲INFINITE,對象被觸發信號後,函數纔會返回。
返回值
執行成功,返回值指示出引發函數返回的事件。它可能爲以下值:
WaitForSingleObject函數用來檢測hHandle事件的信號狀態,在某一線程中調用該函數時,線程暫時掛起,如果在掛起的dwMilliseconds毫秒內,線程所等待的對象變爲有信號狀態,則該函數立即返回;如果超時時間已經到達dwMilliseconds毫秒,但hHandle所指向的對象還沒有變成有信號狀態,函數照樣返回。參數dwMilliseconds有兩個具有特殊意義的值:0和INFINITE。若爲0,則該函數立即返回;若爲INFINITE,則線程一直被掛起,直到hHandle所指向的對象變爲有信號狀態時爲止。
返回值:
WAIT_ABANDONED 0x00000080:當hHandle爲mutex時,如果擁有mutex的線程在結束時沒有釋放核心對象會引發此返回值。
WAIT_OBJECT_0 0x00000000 :核心對象已被激活
WAIT_TIMEOUT 0x00000102:等待超時
WAIT_FAILED 0xFFFFFFFF :出現錯誤,可通過GetLastError得到錯誤代碼
在這裏舉個例子:
先創建一個全局Event對象g_event:
CEvent g_event;
在程序中可以通過調用CEvent::SetEvent設置事件爲有信號狀態。
下面是一個線程函數MyThreadPro()
UINT CFlushDlg::MyThreadProc( LPVOID pParam )
{
WaitForSingleObject(g_event,INFINITE);
For(;;)
{
………….
}
return 0;
}
在這個線程函數中只有設置g_event爲有信號狀態時才執行下面的for循環,因爲g_event是全局變量,所以我們可以在別的線程中通過g_event. SetEvent控制這個線程。
還有一種用法就是我們可以通過WaitForSingleObject函數來間隔的執行一個線程函數的函數體
UINT CFlushDlg::MyThreadProc( LPVOID pParam )
{
while(WaitForSingleObject(g_event,MT_INTERVAL)!=WAIT_OBJECT_0)
{
………………
}
return 0;
}
在這個線程函數中可以通過設置MT_INTERVAL來控制這個線程的函數體多久執行一次,當事件爲無信號狀態時函數體隔MT_INTERVAL執行一次,當設置事件爲有信號狀態時,線程就執行完畢了。
5實例分析
#include <windows.h>//頭文件
#include <iostream.h>
//線程函數聲明
DWORD WINAPI Fun1Proc(
LPVOID lpParameter);
DWORD WINAPI Fun2Proc(
LPVOID lpParameter);
//全局變量
int tickets=100;
HANDLE g_hEvent;
void main()
{
HANDLE hThread1;
HANDLE hThread2;
//創建事件,NULL默認安全性;FALSE自動重置事件對象,當線程等到該事件的所有權後,系統自動將該對象設爲無信號狀態;TRUE初始有信號;NULL無名事件
g_hEvent=CreateEvent(NULL,FALSE,TRUE,NULL);
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);//創建線程
hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);//關閉線程
CloseHandle(hThread2);
Sleep(4000);//延時4s
CloseHandle(g_hEvent);//關閉事件
}
//線程函數實現
DWORD WINAPI Fun1Proc(
LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);//等待事件
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell ticket : "<<tickets--<<endl;
SetEvent(g_hEvent);//設置事件有信號
}
else
{
SetEvent(g_hEvent);
break;
}
}
return 0;
}
DWORD WINAPI Fun2Proc(
LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
if(tickets>0)
{
Sleep(1);
cout<<"thread2 sell ticket : "<<tickets--<<endl;
SetEvent(g_hEvent);
}
else
{
SetEvent(g_hEvent);
break;
}
}
return 0;
}