为ReadFile提供有效回调的方法

时间:2017-07-17 23:16:15

标签: c++ winapi readfile hard-drive

在我的工作线程中,我需要能够在用户输入时停止长文件操作。我目前的方法是在一个小缓冲区上重复调用ReadFile,然后在每次迭代后调用回调函数。像这样:

//Error checks are omitted for brevity

for(;;)
{
    ::ReadFile(hFile, SmallBuffer, nSizeOfSmallBuffer, nBytesRead);

    if(!pfnCallbackProc())
    {
        //Abort
        break;
    }
}

BOOL callbackProc()
{
    return ::WaitForSingleObject(hStopEvent, 0) == WAIT_OBJECT_0;
}

此方法有效。但是,当我进行基准测试时,看看它对一个简单的调用运行速度有多慢:

::ReadFile(hFile, FullBuffer, nSizeOfFullBuffer, nBytesRead);

SSD(随机存取磁盘)的差别并不大,但当我从旋转驱动器读取大文件时,它变得非常明显。例如,使用单个ReadFile读取4GB文件大约需要32秒,使用上面的回调使用我的方法大约需要46秒。 (我知道由于在旋转磁盘上重复调用ReadFile,会发生更大的延迟。)

所以我想知道是否有更有效的方法来做到这一点?

1 个答案:

答案 0 :(得分:4)

可能最明显的可能性是使用ReadFileEx进行重叠读取。然后,您可以在必要时使用CancelIo取消I / O.

由于这是重叠的,您可以直接从父线程调用它,而不是创建专用于I / O的线程。主要要求是当调用线程准备处理来自重叠I / O的反馈时,调用线程进入可警告的等待状态。在父线程使用GetMessage循环的典型情况下,您需要将其更改为使用MsgWaitForMultipleObjectsEx。这使您可以继续检索消息,但也进入可警告的等待状态,因此也可以调用传递给ReadFileEx的回调。