第18節(2 / 2)

(SOCKADDR*)&addrTo,sizeof(SOCKADDR));

SetDlgItemText(IDC_EDIT_SEND,"");

}

Lesson 16 線程同步與異步套接字

1. 事件對象

事件對象同上一課中的互斥對象一樣屬於內核對象,它包含三個成員:使用讀數,用於指明該事件是一個自動重置的還是人工重置的事件的布爾值,用於指明該事件處於已通知狀態還是未通知狀態的布爾值.

當人工重置的事件對象得到通知時,等待該事件對象的所有純種無變為可高度線程,而一個自動重置的事件對象得到通知時,等待該事件對象的線程中人有一個變為可高度線程.所以一般使用線程同步時使用自動重置.

創建事件對象:

HANDLE CreateEvent(

LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全選項,默認為NULL

BOOL bManualReset, // reset type,TRUE(人工),FALSE(自動)

BOOL bInitialState, // initial state,TRUE(有信號狀態)

LPCTSTR lpName // object name.事件對象名

);

BOOL SetEvent(HANDLE hEvent);把指定的事件對象設置為有信號狀態◢本◢作◢品◢由◢思◢兔◢網◢提◢供◢線◢上◢閱◢讀◢

BOOL ReSetEvent(HANDLE hEvent);把指定的事件對象設置為無信號狀態

BOOL CloseHandle( HANDLE hObject ); // handle to object關閉事件對象

DWORD WaitForSingleObject(//請求內核對象,一旦得到事件對象,就進入代碼中

HANDLE hHandle, // handle to object

DWORD dwMilliseconds // time-out interval

);

以下是一個模擬火車站售票的多線程程序(使用事件對象實現線程同步)

#include //加入頭文件,Window API庫

#include //C 標準輸入輸出庫

int tickets = 100;//共享的資源,火車票

HANDLE g_hEvent;//全局的事件對象句柄

//線程處理函數原型聲明

DWORD WINAPI Thread1Proc(

LPVOID lpParameter // thread data

);

DWORD WINAPI Thread2Proc(

LPVOID lpParameter // thread data

);

void main(){

// g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

//創建一個人工重置的匿名事件對象,當調用SetEvent時所有的線程都可以執行,不能實現同步

// SetEvent(g_hEvent);//將事件對象設置為有信號狀態

g_hEvent = CreateEvent(NULL, FALSE, FALSE, "tickets");

//創建一個自動重置的有名事件對象,當調用SetEvent時隻有一個線程可以執行

SetEvent(g_hEvent);

//可以通過創建有名的事件對象來實現隻有一個程序實例運行

if (g_hEvent)//有值

{

if (ERROR_ALREADY_EXISTS == GetLastError())//以事件對象存在為條件實現隻有一個實例運行限製,因為事件對象是內核對象,由操作係統管理,因此可以在多個線程間訪問