具有多线程成员函数的类

时间:2011-03-05 02:56:39

标签: c++ multithreading class syntax beginthreadex

我有一个类,我试图将其某些成员函数转换为在不同的线程中运行。虽然程序没有问题符合,但它在尝试从图像缓冲区(由不同的线程更新)中读取时崩溃。似乎问题是由_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 个答案:

答案 0 :(得分:1)

这里有几个问题:

  1. 您的代码崩溃了,因为您的getImgFromBuffer函数没有您想要的效果。从查看getImgFromBuffer的主体看,你试图从向量中复制指针值(MyFrame :: ImgBuffer)并使用它覆盖从调用它的函数传入的指针值(即“ img“MyFrame :: changeWP中的变量”。我说“似乎”是因为你在调用getImgFromBuffer之前在MyFrame :: changeWP(IplImage * img = new IplImage)中初始化了“img”变量 - 为什么在分配另一个之前将一个新对象分配给指针,不同之处指针值(当然,导致内存泄漏)?无论如何,赋值当前只是覆盖了getImgFromBuffer函数中的“p”参数的值,该函数是按值传递的,并且在函数退出时将丢失。如果你想让getImgFromBuffer覆盖从调用者传入的指针变量,那么你需要传递一个指向指针变量的指针,如下所示:
  2. 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是一个实例变量,那么您可以让多个Section对象尝试保护单个(静态)资源,而不会相互排斥它们。同样,只有一个窗口,所以这可能不是你的实际问题,但仍然......
    2. 可能还有更多,但这足以开始。