класс с многопоточной функцией-членом - PullRequest
1 голос
/ 05 марта 2011

У меня есть класс, который я пытаюсь преобразовать некоторые из его функций-членов для запуска в разных потоках. Хотя программа выполняется без проблем, но происходит сбой при попытке чтения из буфера изображения (который обновляется другим потоком). Похоже, проблема в том, что аргумент неправильно передается в _beginthread.

Следующий фрагмент кода должен более четко объяснить, что я пытаюсь сделать. По сути, я пытаюсь выполнить функцию-заполнитель «fillBuffer» для заполнения буфера изображения, в то время как остальная часть программы делает что-то еще, включая чтение того же буфера изображения одновременно.

Любая помощь с синтаксисом приветствуется.

 const int MaxImgBufferSize = 5;
        class MyFrame : public wxFrame
        {
        public:
            // constructors
            MyFrame(const wxString& title);   

        private:
            static vector <IplImage*> ImgBuffer;
            void  changeWP(wxCommandEvent&);
            void  fillBuffer();
                void  fillBufferFun();
                static void __cdecl getImgFromBuffer(void *);
                static void __cdecl pushImgBuffer(void *);
        };

    vector<IplImage*> MyFrame::ImgBuffer;

        enter code here

    MyFrame::MyFrame(const wxString& title)
           : wxFrame(...)
    {
       // some stuff here
       InitializeCriticalSection(&Section);
       fillBuffer();

      // some code here calls changeWP(wxCommandEvent&) from time to time
    }

    void MyFrame::fillBuffer()
    {
        while(ImgBuffer.size() <= MaxImgBufferSize)
        {
            fillBufferFun();
        }
    }

void MyFrame::fillBufferFun()
{
   ImgBuffer* img;
   // do something with img
   _beginthread(pushImgBuffer, 0, img);
}

void MyFrame::pushImgBuffer(void *p)
{
    EnterCriticalSection(&Section);
    ImgBuffer.push_back( (IplImage*) p );
    LeaveCriticalSection(&Section);
}

static unsigned int __stdcall getImgFromBuffer(void *);

void MyFrame::changeWP(wxCommandEvent&)
{
    // do someting

    IplImage* img = NULL;// new IplImage;
        _beginthreadex( NULL, 0, MyFrame::getImgFromBuffer, img, 0, NULL );

        // do something with img
        fillBuffer();
}

unsigned int MyFrame::getImgFromBuffer(void *p)
{
    EnterCriticalSection(&Section);
    p = (void *)ImgBuffer[0];
    ImgBuffer.erase(ImgBuffer.begin());
    LeaveCriticalSection(&Section);
    return 0;
}

1 Ответ

1 голос
/ 05 марта 2011

Здесь есть несколько проблем:

  1. Ваш код сбой, потому что ваша функция getImgFromBuffer не имеет эффекта, который вы, похоже, намереваетесь для этого.Из рассмотрения тела getImgFromBuffer кажется, что вы пытаетесь скопировать значение указателя из вектора (MyFrame :: ImgBuffer) и использовать его для перезаписи значения указателя, переданного из вызывающей его функции (т. Е. "img "переменная внутри MyFrame :: changeWP).Я говорю «кажется» из-за вашей инициализации переменной «img» внутри MyFrame :: changeWP (IplImage * img = new IplImage) непосредственно перед тем, как вы вызываете getImgFromBuffer - зачем назначать новый объект указателю непосредственно перед назначением еще одного, другогозначение указателя на него (приводящее, конечно, к утечке памяти)?В любом случае, присваивание в настоящее время просто перезаписывает значение аргумента "p" внутри функции getImgFromBuffer, которое было передано по значению и будет потеряно при выходе из функции.Если вы хотите, чтобы getImgFromBuffer перезаписывал переменную-указатель, переданную от вызывающей стороны, вам нужно передать указатель на переменную-указатель, например:
void MyFrame::changeWP(wxCommandEvent&)
{
    IplImage* img = NULL;  // No memory leak, this time.
    _beginthread(MyFrame::getImgFromBuffer, 0, & img);
    //...
}

void MyFrame::getImgFromBuffer(void ** p)
{
    //...
    *p = (void *)ImgBuffer[0];
    //...
}
  1. Я не вижу, как определяется «Раздел», но является ли он статическим или экземпляром, по крайней мере это плохая форма в любом случае.Если он статический, то вы совершаете ошибку, инициализируя его каждый раз, когда создаете.Я понимаю, что это класс, представляющий окно верхнего уровня, так что вы, вероятно, не будете создавать более одного из них, но это все еще плохая форма.Если Section является переменной экземпляра, то у вас может быть несколько объектов Section, пытающихся защитить один (статический) ресурс без взаимного исключения между ними.Опять же, есть только одно окно, так что это, вероятно, не ваша настоящая проблема, но все же ...

Возможно, есть и другое, но этого достаточно для начала.

...