2010-07-06 7 views
3

Voici ce que je fais en un mot.Qu'est-ce que je fais mal? (multithreading)

Dans mon fichier cpp de classe je:

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

Le fil proc ressemble à ceci:

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 ressemble à ceci:

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); 

    } 
} 

Le code qui appelle la les discussions ressemblent à ceci:

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); 

}

Y at-il un problème avec cela? Je m'attendrais à ce qu'il remplisse ThreadPts [4]; ... Il ne devrait jamais y avoir de conflits comme je l'ai fait. Je reçois habituellement écrit d'erreur à ... le dernier fil où DAT-> whichvector = 3. Si je retire:

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

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

Ensuite, il ne semble pas tomber en panne, ce qui pourrait se tromper?

Merci

Répondre

2

Le problème est que vous passez la même structure dat à chaque fil que l'argument de la ThreadProc.

Par exemple, lorsque vous démarrez fil 1, il n'y a aucune garantie qu'il aura lu les informations contenues dans la structure dat avant votre thread principal commence à charger cette même structure dat les informations pour le fil 2 (et ainsi de suite). En fait, vous utilisez constamment cette structure dat tout au long de la boucle du thread, de sorte que le thread ne sera pas terminé avec la structure qui lui est transmise jusqu'à ce que le thread est fait avec tout son travail.

Notez également que currentvector dans SetCubicBezier() est une référence à data->whichVector, qui fait référence exactement au même emplacement dans un thread. Donc, SetCubicBezier() effectuera push_back() appels sur le même objet dans des threads distincts à cause de cela.

Il existe une solution très simple: vous devez utiliser quatre instances SHAPETHREADDATA distinctes, une pour initialiser chaque thread.

+3

+1, bonne prise. Pour généraliser la même règle, lorsque vous transmettez des données à un thread, il est généralement plus facile de transférer la propriété à ce thread, il appartient donc au thread, et le parent ne le touche plus (au moins jusqu'à ce que le thread signale explicitement et transfère les données au parent). –

+0

Merci beaucoup! – jmasterx

Questions connexes