Класс с многопоточной функцией-членом
У меня есть класс, который я пытаюсь преобразовать некоторые его функции-члены для запуска в разных потоках. Хотя программа выполняется без проблем, но происходит сбой при попытке чтения из буфера изображения (который обновляется другим потоком). Похоже, проблема в том, что аргумент неправильно передается в _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 ответ
Здесь есть пара вопросов:
- Ваш код дает сбой, потому что ваша функция 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]; //... }
- Я не вижу, как определяется "Раздел", но является ли он статическим или экземпляром, по крайней мере, в любом случае это плохая форма. Если он статический, то вы совершаете ошибку, инициализируя его каждый раз, когда создаете. Я понимаю, что это класс, представляющий окно верхнего уровня, так что вы, вероятно, не будете создавать более одного из них, но это все еще дурной тон. Если Section является переменной экземпляра, то у вас может быть несколько объектов Section, пытающихся защитить один (статический) ресурс без взаимного исключения между ними. Опять же, есть только одно окно, так что это, вероятно, не ваша настоящая проблема, но все же...
Там, вероятно, больше, но этого достаточно для начала.