windows核心编程之线程内核对象同步(1)

来源:互联网 发布:http service json 编辑:程序博客网 时间:2024/05/19 04:55

如果要等待内核对象,我们必须要使用相关的函数家族
DWORD WaitForSingleObject(
HANDLE hHandle, // 内核对象句柄
DWORD dwMilliseconds // 超时时间(ms)
);
hHandle:内核对象的句柄(所有创建时带名字参数的都属于内核对象)
dwMilliseconds:超时时间(ms),若是想永久等待,则传入INFINITE(无限时间量)
根据返回值,又分为不同的情况
WAIT_OBJECT_0:等待成功
WAIT_TIMEOUT:等待超时,即等待的时间超过设定的时间,如果是INFINITE则不会返回WAIT_TIMEOUT
WAIT_ABANDONED:只有当此函数等待一个互斥对象的时候,并且,此互斥对象在线程结束之前没有释放,此时,线程就视该互斥对象已经被放弃,等待的函数就返回该值
WAIT_FAILED:等待函数的调用发生了错误

不同的内核对象表现也不一样:
事件内核对象,创建时需要调用CreateEvent
第二个参数选填TRUE或FALSE结果也不一样,如果选择FALSE就是自动清除事件,那么使用waitforsingleobject成功等待之后,事件对象会自动复位,同时,众多等待的线程中,只有一个线程进入可调度状态
如果为TRUE就是手动清除事件,waitforsingleobject成功等待之后,事件对象不会自动复位,同时,所有等待的线程都进入可调度状态

而对于信标内核对象,创建时需要使用CreateSemaphore,该函数第二个参数为初始信号量,第三个参数为最大信号量,只有当前信号量大于0的时候,waitforsingleobject才能成功等待,成功等待之后信号量的数量减1,需要调用ReleaseSemaphore才能增加信号量
waitforsingleobjectex
和waitforsingleobject唯一的差别是最后一个参数,如果为false,则与不带ex的版本没有差别,若为TRUE,则会等待APC对象或者一个异步读写完成后的回调函数,当使用ReadFileEx或者WriteFileEx时,一个回调函数就被排到线程的回调函数队列中,用此函数可以完成等待
或者使用 QueueUserAPC时,一个APC对象也会被排到线程的APC队列中
我先举个例子
ReadFileEx

#include <windows.h>#include <iostream>using namespace std;VOID CALLBACK FileIOCompletionRoutine(DWORD dwErrorCode,DWORD dwNumberOfBytesTransfered,LPOVERLAPPED lpOverlapped);int main(){    HANDLE hFile=CreateFile(TEXT("E:\\sql使用说明.txt"),GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,NULL);    if(hFile==INVALID_HANDLE_VALUE)    {        cout<<"打开文件失败"<<endl;        return 1;    }    DWORD FileSize=GetFileSize(hFile,NULL);    char* buf=new char[FileSize];    OVERLAPPED overlap={0};    BOOL suc=ReadFileEx(hFile,buf,FileSize,&overlap,FileIOCompletionRoutine);    if(!suc)    {        cout<<"读取文件失败"<<endl;        return 2;    }    //SleepEx(INFINITE,TRUE);    WaitForSingleObjectEx(GetCurrentThread(),INFINITE,TRUE);    CloseHandle(hFile):    //cout<<buf;    //WaitForSingleObjectEx(hFile,INFINITE,TRUE);    return 0;}VOID CALLBACK FileIOCompletionRoutine(DWORD dwErrorCode,DWORD dwNumberOfBytesTransfered,LPOVERLAPPED lpOverlapped){    cout<<"文件读写结束"<<endl;}

测试结果
这里写图片描述
要说明的是waitforsingleobjectex需要等待的对象必须是调用ReadFileEx或者WriteFileEx的线程内核对象,当然还有其他函数比如SleepEx等等
DWORD WaitForMultipleObjects(
DWORD nCount, //数组中的句柄数量
CONST HANDLE *lpHandles, // 句柄数组
BOOL bWaitAll, // 是否等待全部,TRUE为等待全部
DWORD dwMilliseconds // 超时时间
);
nCount:这个值最小为1,最大为MAXIMUM_WAIT_OBJECTS(64)
lpHandles:一个指向句柄数组的指针
bWaitAll:是否等待全部,这里选择不同,返回值也会有差异,我会在下面做说明
dwMillSeconds:超时时间,永久等待(INFINITE)
返回值
这里写图片描述
如果返回值为WAIT_FAILED:表示等待函数调用失败

WaitForMultipleObjectsEx:也是多了一个参数,这个参数和WaitForSingleObjectEx介绍的也差不多

阅读全文
0 0