C ++中的异步文件I / O.

时间:2011-09-26 10:18:24

标签: c++ windows multithreading io

我无法在C ++中找到有关异步读取和写入的信息。所以我编写代码,函数read()正常工作,但同步没有。 Sync()函数不等待读取结束。 对于我的观点,线程中的变量state_read具有不正确的值。请理解我为什么。

struct IOParams{
    char* buf;
    unsigned int nBytesForRead;
    FILE* fp;
}; 

struct AsyncFile {
     FILE* fp;
     bool state_read;
     HANDLE hThreadRead;
     IOParams read_params;

     void AsyncFile::read(char* buf, unsigned int nBytesForRead){
       sync();
       read_params.buf = buf;
       read_params.fp = fp;
       read_params.nBytesForRead = nBytesForRead;
       hThreadRead = CreateThread(0,0,ThreadFileRead,this,0);
     }

     void AsyncFile::sync() {    
       if (state_read) {
           WaitForSingleObject(hThreadRead,INFINITE);
             CloseHandle(hThreadRead);    
       }
       state_read = false;
    }
};


DWORD WINAPI ThreadFileRead(void* lpParameter) {    
    AsyncFile* asf = (AsyncFile*)lpParameter;
    asf->setReadState(true);
    IOParams & read_params = *asf->getReadParams();
    fread(read_params.buf, 1, read_params.nBytesForRead, read_params.fp);
    asf->setReadState(false);
    return 0;
}

也许您知道如何以更合理的方式编写异步读取。

1 个答案:

答案 0 :(得分:2)

  

也许您知道如何以更合理的方式编写异步读取。

由于您的问题被标记为“Windows”,因此您可能会查看FILE_FLAG_OVERLAPPEDReadFileEx,它们在没有额外线程的情况下进行异步读取(通过事件,回调或完成端口进行同步)。

如果你坚持使用一个单独的加载器线程(可能有正当理由,尽管很少),你不希望从两个线程重复读取和写入一个标志,并将其用于同步。虽然您的代码看起来正确,但仅仅是预期不能正常工作的事实表明这是一个坏主意。
始终使用正确的同步原语(事件或信号量)进行同步,不要篡改某些(可能不一致)写入和从不同线程读取的标志。 或者,如果你不想要一个额外的事件对象,你可以总是等待线程无条件地死掉(但是,阅读下一段)。

通常,产生一个线程并让它在每次读取时死亡都不是一个好的设计。不仅产生一个线程相当大的开销(包括CPU和内存),它还可以引入难以预测的“有趣效果”,并且结果是完全反优化。想象一下,例如有50个线程在寻找硬盘时捶打,所有这些都试图获得一点点。这肯定是异步的,但它也会慢一百倍 如果您不想使用操作系统的本机异步机制,那么使用一小部分工作者(强调 small )可能是一个非常优秀的设计。