WIN32多線程程式設計學習筆記(第六章 上)

來源:互聯網
上載者:User
我們知道當程式調用I/O裝置處理一些事情時,讓主程式停下來乾等I/O的完成是沒有效率的。對這個問題有下面幾種解決方案: 方法一:使用另一個線程進行I/O。但從以前的學習中也知道,協調線程間的關係是一件麻煩的事情,需要小心的設計;所以這個方案可行,但是麻煩。 方法二:使用overlapped I/O。正如書上所說:“overlapped I/O是WIN32的一項技術,你可以要求作業系統為你傳送資料,並且在傳送完畢時通知你。這項技術使你的程式在I/O進行過程中仍然能夠繼續處理事務。事實上,作業系統內部正是以線程來I/O完成overlapped I/O。你可以獲得線程的所有利益,而不需付出什麼痛苦的代價”。哈!這真是一個好方法!!! 下面的內容就是來談怎樣使用overlapped I/O:  進行I/O操作時,指定overlapped方式使用CreateFile(),將其第6個參數指定為FILE_FLAG_OVERLAPPED,就是準備使用overlapped的方式構造或開啟檔案;如果採用overlapped,那麼ReadFile()、WriteFile()的第5個參數必須提供一個指標,指向一個OVERLAPPED結構。OVERLAPPED用於記錄了當前正在操作的檔案一些相關資訊。 //下面引用書上的例子,來說明overlapped//功能:從指定檔案的1500位置讀入300個位元組 int main() {     BOOL rc;     HANDLE hFile;     DWORD numread;     OVERLAPPED overlap;     char buf[512];     char szPath=”x://xxxx/xxxx”;     //檢查系統,確定是否支援overlapped,(NT以上作業系統支援OVERLAPPED)     CheckOsVersion();     // 以overlapped的方式開啟檔案     hFile = CreateFile( szPath,                     GENERIC_READ,                     FILE_SHARE_READ|FILE_SHARE_WRITE,                     NULL,                     OPEN_EXISTING,                     FILE_FLAG_OVERLAPPED ,                     NULL                 );     // OVERLAPPED結構實始化為0 memset(&overlap, 0, sizeof(overlap)); //指定檔案位置是1500;     overlap.Offset = 1500;   rc = ReadFile (hFile,buf,300,&numread,&overlap); //因為是overlapped操作,ReadFile會將讀檔案請求放入讀隊列之後立即返回(false), //而不會等到檔案讀完才返回(true)     if (rc) { //檔案真是被讀完了,rc為true       // 或當資料被放入cache中,或作業系統認為它可以很快速地取得資料,rc為true     }     else     {         if (GetLastError() == ERROR_IO_PENDING)         { //當錯誤是ERROR_IO_PENDING,那意味著讀檔案的操作還在進行中 //等候,直到檔案讀完             WaitForSingleObject(hFile, INFINITE); rc = GetOverlappedResult(hFile,&overlap,&numread, FALSE ); //上面二條陳述式完成的功能與下面一條語句的功能等價: // GetOverlappedResult(hFile,&overlap,&numread, TRUE );          }          else          {             //出錯了         }     }     CloseHandle(hFile);     return EXIT_SUCCESS; }  讀過上面的程式,對overlapped就有一個大概的印象;接著我們繼續探索overlapped I/O的強大功能。  在實際工作中,可能會有多個操作同時使用 同一個 檔案handle,那麼上面的程式就不再適用了。怎麼辦?我們可以利用OVERLAPPED結構中提供的event來解決上面遇到的問題。注意,你所使用的event對象必須是一個MANUAL型的;否則,可能產生競爭條件。原因見書P159。 //程式片段: int main() {     int i;     BOOL rc;     char szPath=”x://xxxx/xxxx”;     // 以overlapped的方式開啟檔案     ghFile = CreateFile( szPath,                     GENERIC_READ,                     FILE_SHARE_READ|FILE_SHARE_WRITE,                      NULL,                     OPEN_EXISTING,                     FILE_FLAG_OVERLAPPED,                     NULL                 );        for (i=0; i<MAX_REQUESTS; i++)     {         //將同一檔案按幾個部分按overlapped方式同時讀         //注意看QueueRequest函數是如何運做的         QueueRequest(i, i*16384, READ_SIZE);     } // 等候所有操作結束; //隱含條件:當一個操作完成時,其對應的event對象會被啟用     WaitForMultipleObjects(         MAX_REQUESTS, ghEvents , TRUE, INFINITE      );       // 收尾操作     for (i=0; i<MAX_REQUESTS; i++)     {         DWORD dwNumread;         rc = GetOverlappedResult(                                 ghFile,                                 &gOverlapped[i],                                 &dwNumread,                                 FALSE                             );         CloseHandle(gOverlapped[i].hEvent);     }       CloseHandle(ghFile);       return EXIT_SUCCESS; }   //當讀操作完成以後, gOverlapped[nIndex].hEvent 會系統被激發 int QueueRequest(int nIndex, DWORD dwLocation, DWORD dwAmount) {     //構造一個MANUAL型的event對象 ghEvents[nIndex] = CreateEvent(NULL, TRUE, FALSE, NULL); //將此event對象置入OVERLAPPED結構     gOverlapped[nIndex].hEvent = ghEvents[nIndex];     gOverlapped[nIndex].Offset = dwLocation;       for (i=0; i<MAX_TRY_COUNT; i++) {     //檔案ghFile唯一         rc = ReadFile( ghFile , gBuffers[nIndex],&dwNumread,&gOverlapped[nIndex]);         //處理成功         if (rc) return TRUE;           err = GetLastError();           if (err == ERROR_IO_PENDING)         {             //當錯誤是ERROR_IO_PENDING,那意味著讀檔案的操作還在進行中             return TRUE;         }           // 處理一些可恢複的錯誤         if ( err == ERROR_INVALID_USER_BUFFER ||              err == ERROR_NOT_ENOUGH_QUOTA ||              err == ERROR_NOT_ENOUGH_MEMORY )         { Sleep(50);  continue; //重試         }         // 如果GetLastError()返回的不是以上列出的錯誤,放棄         break;     }     return -1; } 嗨!當大家耐著性子看到這裡肯定都在罵,這寫的什麼東西,照本宣科嘛。唉,沒辦法,這個東西不好舉例子,只有寫兩個程式片段,加強記憶了,見諒、見諒!!!

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.