【发布时间】:2013-03-01 21:30:05
【问题描述】:
我正在尝试创建一个函数,ReadFileMany,它模仿 ReadFile 的接口,它给出了一个 list 的(偏移量,长度)对来读取,并且异步读取文件的所有部分。
我在ReadFileMany 内部执行此操作,使用RegisterWaitForSingleObject 指示线程池线程等待I/O 完成,以便它可以再次调用ReadFile 来读取文件的下一部分,等等
我遇到的问题是我似乎无法模仿 ReadFile 的某种行为。
具体来说,文件句柄本身可以像事件一样使用,不需要事件句柄:
OVERLAPPED ov = {0};
DWORD nw;
if (ReadFile(hFile, buf, buf_size, &nw, &ov))
{
if (WaitForSingleObject(hFile, INFINITE) == WAIT_OBJECT_0)
{
...
}
}
当然,如果用户在等待一个文件句柄,他可能会收到一个中间读取已完成的通知,而不是最终读取。
所以,在ReadFileMany 中,我别无选择,只能将hEvent 参数传递给ReadFile,除了最后一部分。
问题是,有没有办法让用户在读取所有部分后仍然等待文件句柄发出信号?
起初答案似乎很明显:在读取 last 部分时避免传递事件句柄!
如果读取成功,则效果很好,但如果出现错误,则效果不佳。如果 ReadFile 在上次读取时突然返回错误,我将需要手动将文件句柄设置为信号状态,以便让读者从对 @987654334 的潜在调用中醒来@。
但似乎没有办法在不执行实际 I/O 的情况下将 文件句柄 设置为信号状态...所以这就是我卡住的地方:我有什么办法可以编写这个函数,使其在外部表现得像ReadFile,还是不可能正确地做到这一点?
【问题讨论】:
-
您从哪里得到可以将文件句柄传递给
WaitForSingleObject()的想法?文件句柄不是可等待对象,因此您不能等待它。 -
ReadFileScatter 你想写什么?
-
@Damon:不;实际上恰恰相反。
ReadFileScatter中的“scatter”指的是内存缓冲区(内存中的分散页面),而ReadFileMemory中的“many”指的是文件的不同部分。 -
@RemyLebeau:是的,你确实可以。 (试试看。)显然
ReadFile文档似乎避免提及它,但是如果您查看ZwReadFile,您会发现这是完全有效的,并且文件句柄可以像事件句柄一样发出信号: “调用线程可以通过等待文件句柄来同步读取操作的完成。每次在句柄上发出的 I/O 操作完成时,都会向句柄发出信号。” -
@Mehrdad:根据该文档,它仅在使用
SYNCHRONIZE访问权限打开文件且一次只执行一个 I/O 操作时才有效。应使用ZwWaitForSingleObject()完成等待。CreateFile()、ReadFile()或WaitFor...()文档均未提及有关文件句柄被支持为可等待对象的任何内容,因此我真的不会依赖这种行为。ZwReadFile()是比ReadFile()更低级别的 API,因此不要将更低级别和更高级别的 API 语义混合在一起。
标签: c winapi visual-c++ readfile