線程同步 事件 Event 內核對象 CreateEvent

0、思考

關鍵代碼段可以解決線程間同步,進程間怎麼辦?

1、相關api

CreateEvent
CreateEventEx
SetEvent
ResetEvent
CloseHandle
OpenEvent
PulseEvent
WaitForSingleObject
WaitForMultipleObjects

2、寫在前面

特點:用於進程或線程間同步。

3、api說明

// 創建一個事件內核對象。
// lpEventAttributes:事件對象安全屬性;(通常爲NULL)
// bManualReset:手動重置(true),被觸發時正在等待該事件的所有線程都將被變成可調度狀態,需自行調用ResetEvent把事件變爲未通知狀態
    (通常n個線程等待一個線程時,n個線程沒有順序關係和互斥關係則可使用手動重置);自動重置(true),被觸發時只有一個正在等待該事件的
    線程會變爲可調度狀態,同時對象會自動重置爲未觸發狀態;(通常爲false)
// bInitialState:初始化爲觸發狀態(true),未觸發狀態(false);(通常爲false)
// lpName:有名事件對象,用於進程間同步。
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateEventA(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in     BOOL bManualReset,
    __in     BOOL bInitialState,
    __in_opt LPCSTR lpName
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateEventW(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in     BOOL bManualReset,
    __in     BOOL bInitialState,
    __in_opt LPCWSTR lpName
);
#ifdef UNICODE
#define CreateEvent  CreateEventW
#else
#define CreateEvent  CreateEventA
#endif // !UNICODE

// dwFlags:CREATE_EVENT_INITIAL_SET,觸發狀態;CREATE_EVENT_MANUAL_RESET,手動重置事件;(通常爲0)
// dwDesiredAccess:對事件有何訪問權限;(通常爲EVENT_MODIFY_STATE或者EVENT_ALL_ACCESS)
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateEventExA(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in_opt LPCSTR lpName,
    __in     DWORD dwFlags,
    __in     DWORD dwDesiredAccess
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
CreateEventExW(
    __in_opt LPSECURITY_ATTRIBUTES lpEventAttributes,
    __in_opt LPCWSTR lpName,
    __in     DWORD dwFlags,
    __in     DWORD dwDesiredAccess
);
#ifdef UNICODE
#define CreateEventEx  CreateEventExW
#else
#define CreateEventEx  CreateEventExA
#endif // !UNICODE

// 事件變成觸發狀態
WINBASEAPI
BOOL
WINAPI
SetEvent(
    __in HANDLE hEvent
);

// 事件變成未觸發狀態
WINBASEAPI
BOOL
WINAPI
ResetEvent(
    __in HANDLE hEvent
);

// 關閉一個打開的對象句柄。
WINBASEAPI
BOOL
WINAPI
CloseHandle(
    __in HANDLE hObject
);

// 打開一個已經存在的命名事件對象。
// dwDesiredAccess:指定想要的訪問權限:EVENT_ALL_ACCESS請求對事件對象的完全訪問;EVENT_MODIFY_STATE允許使用;通常爲EVENT_ALL_ACCESS。
// bInheritHandle:是否希望子進程繼承事件對象的句柄,通常爲false。
// lpName:要打開的事件對象的名稱。
WINBASEAPI
__out_opt
HANDLE
WINAPI
OpenEventA(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCSTR lpName
);
WINBASEAPI
__out_opt
HANDLE
WINAPI
OpenEventW(
    __in DWORD dwDesiredAccess,
    __in BOOL bInheritHandle,
    __in LPCWSTR lpName
);
#ifdef UNICODE
#define OpenEvent  OpenEventW
#else
#define OpenEvent  OpenEventA
#endif // !UNICODE

// 設置特定的事件對象爲有信號狀態,然後釋放相關的等待線程,再置時間對象爲無信號狀態。(ps:如果在一個線程PluseEvent()的時候,恰好沒有
    線程處於等待狀態,那麼這個事件將丟失)(關注:SignalObjectAndWait)
WINBASEAPI
BOOL
WINAPI
PulseEvent(
    __in HANDLE hEvent
);

4、C++封裝

#pragma once

#include <windows.h>


class ncEvent
{
public:
    ncEvent (BOOL bManualReset = FALSE, BOOL bInitialState = FALSE, LPCTSTR lpName = NULL)
    {
        _event = CreateEvent (NULL, bManualReset, bInitialState, lpName);
    }

    ~ncEvent ()
    {
        CloseHandle (_event);
    }

    BOOL set ()
    {
        return SetEvent (_event);
    }

    BOOL reset ()
    {
        return ResetEvent (_event);
    }

    operator HANDLE ()
    {
        return _event;
    }

    DWORD wait (DWORD timeout = INFINITE) 
    {
        return WaitForSingleObject (_event, timeout);
    }

private:
    HANDLE _event;
};

5、順藤摸瓜

typedef struct _SECURITY_ATTRIBUTES {
    DWORD nLength;
    LPVOID lpSecurityDescriptor;
    BOOL bInheritHandle;
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;

鳴謝

覺的我寫的幫幫噠, 發個紅包賞賞賞

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章