using namespace std;
HANDLE hfile;
OVERLAPPED ov = { 0 };
void __stdcall apc(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped) {
cout << "enter apc" << endl;
cout << dwErrorCode << ", " << dwNumberOfBytesTransfered << endl;
}
unsigned __stdcall proc2(void*) {
cout << "enter thread 22222" << endl;
WaitForSingleObject(ov.hEvent, INFINITE);
cout << "thread 2222 have wait event ok..." << endl;
return 0;
}
unsigned __stdcall proc1(void*) {
hfile = CreateFile(L"D:\\test.file", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
if (hfile == INVALID_HANDLE_VALUE) {
cout << "create file failed." << endl;
}
constexpr int size = 110240000;
char* buf = new char[size] {0};
DWORD numsWrite = 0;
DWORD ret = WriteFileEx(hfile, buf, size, &ov, apc);
DWORD lastError = GetLastError();
if (ret == 0) {
cout << "write failed " << lastError << endl;
return 0;
}
DWORD dw = WaitForSingleObjectEx(hfile, INFINITE, FALSE);
//DWORD dw = WaitForSingleObjectEx(hfile, INFINITE, TRUE);
//SleepEx(INFINITE, TRUE);
cout << "after sleep" << endl;
return 0;
}
int main() {
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
//ov.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
HANDLE t1 = (HANDLE)_beginthreadex(NULL, 0, proc1, NULL, NULL, NULL);
HANDLE t2 = (HANDLE)_beginthreadex(NULL, 0, proc2, NULL, NULL, NULL);
WaitForSingleObject(t1, INFINITE);
WaitForSingleObject(t2, INFINITE);
CloseHandle(t1);
CloseHandle(t2);
return 0;
}
想验证两个点:
1.调用WriteFileEx传入OVERLAPPED,其中的hEvent有啥用?会不会完成I/O以后把event变成激发态?
结果:用proc2测试,如果会将event激发,则会打印两句,结果验证只有一句。这个hEvent没啥用处。书上也写了,哈哈。
ov.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
2.WriteFileEx以后调用这三个函数等待有啥不同?
//DWORD dw = WaitForSingleObjectEx(hfile, INFINITE, FALSE);
//DWORD dw = WaitForSingleObjectEx(hfile, INFINITE, TRUE);
SleepEx(INFINITE, TRUE);
答案:这个是我一个脑洞。我当时有点不太理解。其实很简单
WaitForSingleObjectEx(hfile, INFINITE, FALSE);,则退化为WaitForSingleObject(hfile, INIFINITE),而这个等待,其实是对文件的句柄的等待。文件句柄在有异步I/O的情况下是非激发态,I/O完成以后激发态。所以这里实际是windows核心编程里的“触发设备内核对象”,所以返回的是WAIT_OBJECT_0,不推荐。
WaitForSingleObjectEx(hfile, INFINITE, TRUE); 经过验证,照道理来说,I/O完成以后,此时hfile已经激发了。但是这里由于此时线程处于可提醒状态,实际I/O完成以后,系统往线程插入了APC队列,执行了apc函数,返回了WAIT_IO_COMPLETION(192),wait就结束了。
SleepEx(INFINITE, TRUE);这个是最正确的调用,本来就跟hfile无关啊。返回的是192,因为apc执行了。
最后的脑洞:如果我用一个激发态的event去调用,如下,结果会咋样?
验证:结果不定,size=1102400000时,wait 返回了0,显然是event生效了,没有执行apc。
size=11024000(少两个0)的时候,是apc生效了,但是event还是可以继续wait。
结论:我们别这样瞎搞