关闭句柄后调用的 ReadDirectoryChangesW 异步完成例程

ReadDirectoryChangesW Asynchronous Completion routine called after I close the handle

我正在使用 ReadDirectoryChangesW 来监视目录中的文件何时发生更改。我将它的异步版本与完成例程函数一起使用(根据文档)。

一切正常,直到我希望停止监视该文件夹。

为了停止监控,我调用了 Close 函数。

问题是我仍然收到最后一条通知,但到那时我已经毁掉了我的 LPOVERLAPPED 价值。

如何停止 ReadDirectoryChangesW 并防止我的 MyCompletionRoutine 函数被调用。

// get the handle    
_handle = CreateFileW( ... )

void Read()
{
  ...
  ReadDirectoryChangesW( _handle, ..., &MyCompletionRoutine );
  ...
}

void Close()
{
  ::CancelIo(_handle );           
  ::CloseHandle(_handle );
}

void __stdcall MyCompletionRoutine (
    const unsigned long dwErrorCode,
    const unsigned long dwNumberOfBytesTransfered,
    _OVERLAPPED* lpOverlapped )
{
  // ... do stuff and start a read again
  Read();
}

在上面的代码中我可能调用了 Read 但我想在调用 MyCompletionRoutine 之前停止。

不确定这是否有帮助,但我收到的错误消息是 317

您正在关闭您的 HANDLE 并释放您的 OVERLAPPED 太早了。

CancelIo()(以及它的跨线程兄弟,CancelIoEx())简单地将活动的I/O操作标记为已取消然后退出,但您仍然需要实际等待这些操作完成完全完成,然后才能释放他们的 OVERLAPPED.

如果操作在完成其工作之前注意到取消,它将停止其工作并报告完成并返回错误代码 ERROR_OPERATION_ABORTED,否则它将正常完成其工作并使用适当的错误代码报告完成错误代码。

调用CancelIo/Ex()后,您需要继续等待和处理已完成的操作,直到没有更多操作可等待。

也就是说,调用CancelIo()后确实可以调用MyCompletionRoutine(),再次调用Read()之前需要检查ERROR_OPERATION_ABORTED。如果在调用 CancelIo() 时有正在进行的读取,则需要等待该读取完成。