我找不到有关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;
}
也许你知道如何以更合理的方式编写异步读取。
最佳答案
Maybe you know how to write the asynchronous reading in more reasonable way.
由于您的问题被标记为“Windows”,您可能会研究 FILE_FLAG_OVERLAPPED
和 ReadFileEx
,它们无需额外线程即可进行异步读取(通过事件、回调进行同步,或完成端口)。
如果您坚持使用单独的加载器线程(可能有充分的理由,尽管很少),您不希望从两个线程重复读取和写入标志并将其用于同步。尽管您的代码看起来是正确的,但仅不能按预期工作这一事实就表明这是一个坏主意。
始终使用正确同步原语(事件或信号量)进行同步,不要篡改从不同线程写入和读取(可能不一致)的某些标志。
或者,如果您不需要额外的事件对象,您可以始终无条件地等待线程终止(但是,请阅读下一段)。
一般来说,生成一个线程并让它在每次读取时死亡并不是一个好的设计。生成线程不仅会产生相当大的开销(对于 CPU 和内存而言),而且还会引入难以预测的“有趣效果”,并最终导致完全反优化。想象一下,例如,有 50 个线程在搜索时对硬盘驱动器进行攻击,所有线程都试图获取其中的一部分。这肯定是异步的,但也会慢一百倍。
如果您不想使用操作系统的 native 异步机制,那么使用少量工作人员(强调小)可能是一个更优越的设计。
关于c++ - C++ 中的异步文件 I/O,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7553640/