2010-07-06 113 views
3

這裏是我正在做的簡而言之。我在做什麼錯? (多線程)

在我班上的CPP文件我有:

std::vector<std::vector<GLdouble>> ThreadPts[4]; 

線程PROC看起來是這樣的:

unsigned __stdcall BezierThreadProc(void *arg) 
{ 
    SHAPETHREADDATA *data = (SHAPETHREADDATA *) arg; 

    OGLSHAPE *obj = reinterpret_cast<OGLSHAPE*>(data->objectptr); 
    for(unsigned int i = data->start; i < data->end - 1; ++i) 
    { 


     obj->SetCubicBezier(
      obj->Contour[data->contournum].UserPoints[i], 
      obj->Contour[data->contournum].UserPoints[i + 1], 
      data->whichVector); 

    } 

    _endthreadex(0); 
    return 0; 

} 

SetCubicBezier看起來是這樣的:

void OGLSHAPE::SetCubicBezier(USERFPOINT &a,USERFPOINT &b, int &currentvector) 
{ 
    std::vector<GLdouble> temp; 
    if(a.RightHandle.x == a.UserPoint.x && a.RightHandle.y == a.UserPoint.y 
     && b.LeftHandle.x == b.UserPoint.x && b.LeftHandle.y == b.UserPoint.y) 
    { 
     temp.clear(); 
     temp.push_back((GLdouble)a.UserPoint.x); 
     temp.push_back((GLdouble)a.UserPoint.y); 

     ThreadPts[currentvector].push_back(temp); 
     temp.clear(); 
     temp.push_back((GLdouble)b.UserPoint.x); 
     temp.push_back((GLdouble)b.UserPoint.y); 


     ThreadPts[currentvector].push_back(temp); 

    } 
} 

代碼調用線程如下所示:

for(int i = 0; i < Contour.size(); ++i) 
{ 
    Contour[i].DrawingPoints.clear(); 

if(Contour[i].UserPoints.size() < 2) 
{ 
    break; 
} 

HANDLE hThread[4]; 
SHAPETHREADDATA dat; 
dat.objectptr = (void*)this; 
dat.start = 0; 
dat.end = floor((Contour[i].UserPoints.size() - 1) * 0.25); 
dat.whichVector = 0; 
dat.contournum = i; 



hThread[0] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0); 

dat.start = dat.end; 
dat.end = floor((Contour[i].UserPoints.size() - 1) * 0.5); 
dat.whichVector = 1; 

hThread[1] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0); 

dat.start = dat.end; 
dat.end = floor((Contour[i].UserPoints.size() - 1) * 0.75); 
dat.whichVector = 2; 

hThread[2] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0); 

dat.start = dat.end; 
dat.end = Contour[i].UserPoints.size(); 
dat.whichVector = 3; 

hThread[3] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0); 

WaitForMultipleObjects(4,hThread,true,INFINITE); 

}

這是否有問題?我期望它能夠填充ThreadPts [4]; ......我應該永遠不會有任何衝突。我通常在...得到錯誤寫在最後一個程序,其中DAT-> whichvector = 3。如果我卸下:

dat.start = dat.end; 
dat.end = Contour[i].UserPoints.size(); 
dat.whichVector = 3; 

hThread[3] = (HANDLE)_beginthreadex(NULL,0,&BezierThreadProc,&dat,0,0); 

然後,它似乎並沒有崩潰,這可能是錯了嗎?

感謝

回答

2

的問題是,你傳遞相同dat結構,每個線程作爲參數傳遞給ThreadProc的。

例如,當您啓動線程1,有沒有保證,這將有你的主線程開始加載同樣的dat結構與信息線程2(等)之前,請閱讀dat結構的信息。事實上,在整個線程循環中,你總是直接使用這個結構,所以線程不會被傳遞給它的結構完成,直到線程基本完成所有工作。

另請注意,currentvectorSetCubicBezier()是參考data->whichVector,它指的是線程中完全相同的位置。因此,SetCubicBezier()將因爲此而在獨立線程中的同一對象上執行push_back()調用。

有一個非常簡單的修復方法:您應該使用四個獨立的SHAPETHREADDATA實例 - 一個用於初始化每個線程。

+3

+1,很好。爲了概括相同的規則,當你將一些數據傳遞給一個線程時,通常將所有權轉移給該線程是最容易的,因此它屬於該線程,並且父母再也不會觸及它(至少在線程明確表示它已完成並將數據傳回給父母)。 – 2010-07-06 21:23:08

+0

非常感謝! – jmasterx 2010-07-07 00:06:32