Что я делаю неправильно?(Многопоточный) - PullRequest
3 голосов
/ 07 июля 2010

Вот что я делаю в двух словах.

В файле cpp моего класса:

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

Нить выглядит следующим образом:

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

Тогда, похоже, он не падает, что может быть не так?

Спасибо

1 Ответ

2 голосов
/ 07 июля 2010

Проблема в том, что вы передаете одну и ту же структуру dat каждому потоку в качестве аргумента для threadproc.

Например, когда вы запускаете поток 1, нет гарантии, что он прочтет информацию в структуре dat до того, как ваш основной поток начнет загружать ту же самую структуру dat с информацией для потока 2 (и т. Д. ). Фактически, вы постоянно напрямую используете эту dat структуру во всем цикле потока, поэтому поток не будет завершен со структурой, переданной ему, до тех пор, пока поток в основном не завершит всю свою работу.

Также обратите внимание, что currentvector в SetCubicBezier() является ссылкой на data->whichVector, которая ссылается на точно такое же местоположение в потоках. Поэтому SetCubicBezier() будет выполнять вызовы push_back() для одного и того же объекта в отдельных потоках из-за этого.

Есть очень простое решение: вы должны использовать четыре отдельных SHAPETHREADDATA экземпляра - по одному для инициализации каждого потока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...