2011-11-15 117 views
1

我有點生疏,特別是在Windows中的線程程序。 我在Matlab中創建了一個簡單的mex文件,用於讀取多個文件,每個文件在其自己的線程中讀取。 這個文件並沒有做任何真正有用的事情,但它是一個更復雜版本的前身,它將使用放入此文件的所有功能。 下面是代碼:C++ windows線程和互斥問題

#include <windows.h> 
#include "mex.h" 
#include <fstream> 

typedef unsigned char uchar; 
typedef unsigned int uint; 

using namespace std; 

int N; 
int nThreads; 
const int BLOCKSIZE = 1024; 
char * buffer; 
char * out; 
HANDLE hIOMutex; 

DWORD WINAPI runThread(LPVOID argPos) { 
    int pos = *(reinterpret_cast<int*>(argPos)); 

    DWORD dwWaitResult = WaitForSingleObject(hIOMutex, INFINITE); 

    if (dwWaitResult == WAIT_OBJECT_0){ 
     char buf[20]; 
     sprintf(buf, "test%i.dat", pos); 
     ifstream ifs(buf, ios::binary); 

     if (!ifs.fail()) { 
      mexPrintf("Running thread:%i\n", pos); 
      for (int i=0; i<N/BLOCKSIZE;i++) { 
       if (ifs.eof()){ 
        mexPrintf("File %s exited at i=%i\n", buf, (i-1)*BLOCKSIZE); 
        break; 
       } 
       ifs.read(&buffer[pos*BLOCKSIZE], BLOCKSIZE); 
      } 
     } 
     else { 
      mexPrintf("Could not open file %s\n", buf); 
     } 

     ifs.close(); 
     ReleaseMutex(hIOMutex); 
    } 
    else 
     mexPrintf("The Mutex failed in thread:%i \n", pos); 


    return TRUE; 
} 

// 0 - N is data size 
// 1 - nThreads is number of threads 
// 2 - this is the output array 

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray*prhs[]) { 
    N = mxGetScalar(prhs[0]); 
    nThreads = mxGetScalar(prhs[1]); 
    out = (char*)mxGetData(prhs[2]); 
    buffer = (char*)malloc(BLOCKSIZE*nThreads); 
    hIOMutex= CreateMutex(NULL, FALSE, NULL); 

    HANDLE *hArr = (HANDLE*)malloc(sizeof(HANDLE)*nThreads); 
    int *tInd = (int*)malloc(sizeof(int)*nThreads); 

    for (int i=0;i<nThreads;i++){ 
     tInd[i]=i; 
     hArr[i] = CreateThread(NULL, 0, runThread, &tInd[i], 0, NULL); 
     if (!hArr[i]) { 
      mexPrintf("Failed to start thread:%i\n", i); 
      break; 
     } 
    } 

    WaitForMultipleObjects(nThreads, hArr, TRUE, INFINITE); 

    for (int i=0;i<nThreads;i++) 
     CloseHandle(hArr[i]); 

    CloseHandle(hIOMutex); 
    mexEvalString("drawnow"); 
    mexPrintf("Finished all threads.\n"); 

    free(hArr); 
    free(tInd); 
    free(buffer); 

我編譯它像這樣在Matlab:

mex readFile.cpp 

,然後運行它像這樣:

out = zeros(1024*1024,1,'uint8'); 
readFile(1024*1024,nFiles,out); 

的問題是,當我設置NFILES小於或等於64,一切按預期工作,我得到以下輸出:

Running thread:0 
. 
. 
. 
Running thread:62 
Running thread:63 
Finished all threads. 

但是當我設置NFILES爲65歲或更大的獲取:

Running thread:0 
Running thread:1 
Running thread:2 
Running thread:3 
The Mutex failed in thread:59 
The Mutex failed in thread:60 
The Mutex failed in thread:61 
. 
. 
. 
(up to nFiles-1) 
Finished all threads. 

我也測試了它,不必穿線,它工作正常。

我看不到我在做什麼錯誤,或者爲什麼使用互斥量的截斷會如此武斷,所以我假設我沒有考慮到這一點。 任何人都可以看到我有一個明顯的錯誤與我看到的錯誤有關嗎?

回答

3

WaitForMultipleObjects的文檔中,「對象句柄的最大數量爲MAXIMUM_WAIT_OBJECTS。」,在大多數系統上爲64。

這也是(幾乎)重複的this thread。總結其實只是,是的,限制是64,也可以使用WaitForMultipleObjects備註部分的信息構建一個等待線程的樹。

+0

謝謝!我認爲這是這樣的,但不知道如何看待。 – twerdster

+0

@twerdster - 我的方式通常只是查看失敗函數的函數引用,或者相關的東西。在這種情況下,'WaitForSingleObject'很可能失敗了,因爲除非線程被殺死,否則它不可能失敗,請查看它可能被殺死的地方,因此'WaitForMultipleObjects'可能會失敗。你可以看到的限制也有幫助,因爲你可以搜索文件的限制和其他東西。 – slugonamission