(内核对象机制,优点:适应性好,跨进程访问;缺点:速度慢)
一、等待函数(使线程进入等待状态):
a) DWORD WaitForSingleObject(HANDLE, DWORD dwMilliseconds); //INFINITE
返回值指明变为可调度状态的原因,所等待的对象变为已通知:WAIT_OBJECT_0;超时:WAIT_TIMEOUT;传入了无效句柄:WAIT_FAILED
b) DWORD WaitForMultipleObjects(
DWORD dwCount,//查看多少个内核对象,1~MAXIMUM_WAIT_OBJECTS
CONST HANDLE* phObjects, //句柄数组
BOOL fWaitAll, // = FALSE,当任一对象成为已通知状态;=TRUE,所有
DWORD dwMilliseconds);
返回值类似a),使用:dwRet - WAIT_OBJECT_0可以作为句柄数组的索引。
二、“事件”内核对象
a) HANDLE CreateEvent(
PSECURITY_ATTRIBUTES psa,
BOOL fManualReset, // = TRUE,人工重置;= FALSE,自动
BOOL fInitialState, // = TRUE,初始化为已通知状态
PCTSTR pszName);
b) 其他进程可以获得对该对象的访问权(详见C3、共享内核对象)。
c) 不再需要时,应该用CloseHandle。
d) 将事件改为已通知状态:BOOL SetEvent(HANDLE);
e) 重置为未通知状态:BOOL ResetEvent(HANDLE);(如为自动重置事件(fManualReset = FALSE),当线程成功等待到该对象时,系统自动重置为未通知状态,不必调用ResetEvent。
f) 不常用的函数:BOOL PulseEvent(HANDLE); // 相当于ResetEvent 后立即SetEvent
三、等待定时器内核对象(按规定的时间间隔发出信号,执行某操作)
a) 创建定时器: HANDLE CreateWaitalbeTimer(psa, BOOL fManualReset, pszName);
b) 打开命名定时器:HANDLE OpenWaitableTimer(…, pszName);
c) 设置成已通知状态:
BOOL SetWaitableTimer( HANDLE hTimer,
const LARGE_INTEGER *pDueTime, // 何时第一次报时
LONG lPeriod, // 间隔时间
PTIMERAPCROUTINE pfnCompletionRoutine,
PVOID pvArgToCompletionRoutine,
BOOL fResume);
d) 取消报时:BOOL CancleWaitableTimer(HANDLE); 当再次调用SetWaitableTimer,则原来的报时条件自动取消。
四、信标内核对象(信号量?)
(用于对资源进行计数:最大资源数量,当前资源数量)。
a) 创建:HANDLE CreateSemaphore(psa,
lInitialCount, // 当前可供使用的资源数
lMaximumCount, // 最大资源数
pszName);
b) 打开:HANDLE OpenSemaphore(fdwAccess, bInheritHandle, pszName);
c) 递增当前资源数:
BOOL ReleaseSemaphore(HANDLE,
lReleaseCount, // 通常传入1
plPreviousCount); // 返回当前资源数量,通常传入NULL
五、互斥对象(mutex)内核对象
能确保线程对单个资源的互斥访问权,包含:使用数量,线程ID(标识拥有的线程),递归计数器(当前线程拥有的次数)。其特性与关键代码段相同,但属于内核对象。常用于保护多线程访问的内存块。
a) 创建:HANDLE CreateMutex(psa,
fInitialOwner, // 通常= FALSE未被任何线程拥有;TRUE创建者拥有
pszName);
b) 打开:HANDLE OpenMutex(fdwAccess, bInheritHandle, pszName);
c) 释放(当前线程不再需要访问资源):BOOL ReleaseMutex(HANDLE);
六、其它线程同步函数:
a) WaitForSingleObject , WaitForMultipleObjects
b) 异步设备I/O:设备对象是可以同步的内核对象,调用WaitForSingleObject,传递文件、套接字、通讯端口的句柄。一旦I/O完成,就可以继续运行。
c) DWORD WaitForInputIdle(hProcess, dwMilliseconds); 该函数一直等到hProcess标识的进程无输入为止(OS对进程的创建有很多I/O操作)。
d) DWORD MsgWaitForMultipleObjects(dwCount, phObjects, bWaitAll, dwMilliseconds, dwWakeMask);
DWORD MsgWaitForMultipleObjectsEx(dwCount, phObjects, dwMilliseconds, dwWakeMask, dwFlags);
与WaitForMultipleObjects相似,在创建窗口和执行与用户界面相关的任务的线程,应该调用Msg…函数。
e) BOOL WatiForDebugEvent(PDEBUG_EVENT pde, DWORD dwMilliseconds); 等待调试事件发生。
f) DWORD SignalObjectAndWait(hObjectToSignal,// 标识互斥对象、信标或事件
hObjectToWaiton,// 标识互斥对象、信标、事件、定时器、进程、线程、作业、控制台输入、修改通知。
dwMilliseconds,
fAlertable);// 标识是否能处理异步过程调用
// 使用这个函数比较有用,不提倡下面代码:
……
SetEvent(hObjectToSignal);
WaitForSingleObject(hObjectToWaiton, INFINITE);
……