2011-09-26 102 views
1

我無法在C++中找到有關異步讀寫的信息。所以我編寫代碼,函數read()可以正常工作,但同步不會。 Sync()函數不會等待讀取結束。 對於我的意見變量state_read在線程中有不正確的值。請理解我爲什麼。C++中的異步文件I/O

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

也許你知道如何以更合理的方式編寫異步閱讀。

由於您的問題被標記的「Windows」,你可能會考慮FILE_FLAG_OVERLAPPEDReadFileEx,這(通過一個事件,一個回調,或完成端口的同步)沒有做額外的線程異步讀取。

如果您堅持使用單獨的加載程序線程(可能有合理的原因,儘管很少),但您不希望從兩個線程中反覆讀寫標誌並將其用於同步。雖然你的代碼看起來是正確的,但事實並非如預期那樣工作,這表明這是一個壞主意。
始終使用正確的同步原語(事件或信號量)進行同步,不要篡改某些標誌(可能不一致)寫入並從不同線程讀取。 另外,如果你不想要一個額外的事件對象,你可以總是等待線程死亡,無條件地(但是,閱讀下一段)。

一般來說,產生一個線程並讓它爲每次讀取而死是不是一個好設計。不僅產生了一個相當大的開銷(CPU和內存),它還可能難以預測「有趣的效果」,併成爲一種全面的反優化。想象一下,例如,有50個線程在尋求硬盤驅動器上抖動,所有這些線程都試圖獲得一點。這肯定是異步的,但速度也會降低一百倍。
如果您不想使用操作系統的本機異步機制,那麼使用少量工人(重點在)可能會是一個非常優秀的設計。