wxQueueEvent and thread Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Post Reply
Laurent Berger
Earned some good credits
Earned some good credits
Posts: 138
Joined: Tue May 20, 2008 1:03 pm

wxQueueEvent and thread

Post by Laurent Berger »

Hi,
My program display video using opencv and wxwidgets 3.0. A thread is calling cv::VideoCapture and send wxCommandEvent to main thread usind pendingEvent.
In the help file there is an example with wxQueueEvent (http://docs.wxwidgets.org/trunk/classwx_thread.html). It is written that wxQueueEvent is threadSafe but AddpendingEvent is not.
In my source code I have tried to implement wxQueueEvent but I have got errors (#define __QUEUE_EVENT__ in source file)
error C2146: erreur de syntaxe : absence de ')' avant l'identificateur 'wxEVT_COMMAND_MYTHREAD_UPDATE' in main.cpp.

Somebody can help me?
Thanks you for yours answers
Attachments
wxOpenCV.zip
(6.59 KiB) Downloaded 179 times
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19162
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxQueueEvent and thread

Post by doublemax »

AddPendingEvent() itself is thread-safe. As long as you only send an integer with the event like in your current code, it's safe to use it.

The only different to wxQueueEvent is, that wxQueueEvent clones the event and creates deep copies of all members, so that no problems with reference counted objects (like wxString) can occur.
error C2146: erreur de syntaxe : absence de ')' avant l'identificateur 'wxEVT_COMMAND_MYTHREAD_UPDATE' in main.cpp.
wxEVT_COMMAND_MYTHREAD_UPDATE is a custom event type that needs to be declared and defined. Did you include the two respective lines?

Code: Select all

// this can be in a header file, so that other classes can use the event type
wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent)

// this must be in a .CPP file so that it only exists once in the project
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent)
Use the source, Luke!
modoran
Knows some wx things
Knows some wx things
Posts: 47
Joined: Tue Mar 23, 2010 1:31 pm
Location: Romania
Contact:

Re: wxQueueEvent and thread

Post by modoran »

There it comes an example from a working project:
header.h:

Code: Select all

wxDECLARE_EVENT ( wxEVT_COMMAND_MYTHREAD_UPDATE,
                  wxThreadEvent );

class CProgressDialog : public ProgressDialog,
    public wxThreadHelper {
    public:
        /** Constructor */
        CProgressDialog ( wxWindow* parent,
                          wxConfig*  cnfg, const wxArrayString& filenames,
                          int categoryIndex = 0 );
        ~CProgressDialog ();
        bool IsOK () { return isOK; }
        //// end generated class members
    protected:
        void OnCancel ( wxCommandEvent& event );
        void OnClipboardCopy ( wxCommandEvent& event );
        void OnThreadUpdate ( wxThreadEvent& event );
        virtual wxThread::ExitCode Entry ();
        wxDECLARE_EVENT_TABLE ();
  
};


implementation file .cpp

Code: Select all

wxDEFINE_EVENT ( wxEVT_COMMAND_MYTHREAD_UPDATE,
                 wxThreadEvent );

BEGIN_EVENT_TABLE ( CProgressDialog,
                        ProgressDialog )
    
END_EVENT_TABLE ();

CProgressDialog::CProgressDialog ( wxWindow*
                                   parent, wxConfig* cnfg,
                                   const wxArrayString& filenames,
                                   int iCat )
    :
    ProgressDialog ( parent )
{
    
    this->Connect ( wxEVT_COMMAND_MYTHREAD_UPDATE,
                    wxThreadEventHandler (
                        CProgressDialog::OnThreadUpdate ) );
// other code
}
CProgressDialog::~CProgressDialog ()
{
    this->Disconnect ( wxEVT_COMMAND_MYTHREAD_UPDATE,
                       wxThreadEventHandler (
                           CProgressDialog::OnThreadUpdate ) );
                           
   
    
    //wxMessageBox("DESTRUCTOR");
}
wxThread::ExitCode CProgressDialog::Entry ()
{
    // IMPORTANT:
    // this function gets executed in the secondary thread context!
    CURLM* multi_handle = curl_multi_init ();

if ( multi_handle == NULL ) {
        wxThreadEvent* evt = new wxThreadEvent (
            wxEVT_COMMAND_MYTHREAD_UPDATE );
        evt->SetInt ( 1 );
        wxQueueEvent ( this, evt );
        return 0;
    }
}
void CProgressDialog::OnThreadUpdate (
    wxThreadEvent& event )
{
// process event here
}


The code is copy-pasted, but I hope you have a starting point now.
Laurent Berger
Earned some good credits
Earned some good credits
Posts: 138
Joined: Tue May 20, 2008 1:03 pm

Re: wxQueueEvent and thread

Post by Laurent Berger »

Thanks you for yours answers.

PS I have found this http://wiki.wxwidgets.org/Custom_Events but I cannot compile this example

@doublemax
I have still erros
>f:\laurent\visual studio 2008\projects\wxopencv\wxopencv\main.cpp(46): warning C4003: nombre de paramètres réels insuffisants pour la macro 'EVT_COMMAND'
1>f:\laurent\visual studio 2008\projects\wxopencv\wxopencv\main.cpp(46): warning C4003: nombre de paramètres réels insuffisants pour la macro 'wxCommandEventHandler'
1>f:\laurent\visual studio 2008\projects\wxopencv\wxopencv\main.cpp(46): error C2146: erreur de syntaxe : absence de ')' avant l'identificateur 'wxEVT_COMMAND_MYTHREAD_UPDATE'
1>f:\laurent\visual studio 2008\projects\wxopencv\wxopencv\main.cpp(46): error C2661: 'wxEventTableEntry::wxEventTableEntry' : aucune fonction surchargée ne nécessite 2 arguments

If I write in main.cpp

#define __QUEUE_EVENT__

#ifdef __QUEUE_EVENT__
wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
#endif

// --------------------------------------------------------------------------
// Table des évènements
// --------------------------------------------------------------------------

wxBEGIN_EVENT_TABLE(IHMOpenCV, wxFrame)
EVT_MENU(IHMOpenCV_QUIT, IHMOpenCV::OnQuit)
EVT_MENU(IHMOpenCV_APROPOS, IHMOpenCV::OnAbout)
EVT_MENU(IHMOpenCV_DBACQ, IHMOpenCV::DebutAcq)
EVT_COMMAND(28, wxEVT_COMMAND_TEXT_UPDATED, IHMOpenCV::OnThreadUpdate)
#ifdef __QUEUE_EVENT__
EVT_COMMAND(wxID_ANY wxEVT_COMMAND_MYTHREAD_UPDATE, IHMOpenCV::OnThreadUpdateQueue) // LINE 46
#endif
EVT_TIMER(wxID_ANY,IHMOpenCV::OnTimerEvent)
wxEND_EVENT_TABLE()

@modoran in your example source abd destination is the same class I think
L.B.
Laurent Berger
Earned some good credits
Earned some good credits
Posts: 138
Joined: Tue May 20, 2008 1:03 pm

Re: wxQueueEvent and thread

Post by Laurent Berger »

I forget a comma in
EVT_COMMAND(wxID_ANY,wxEVT_COMMAND_MYTHREAD_UPDATE, IHMOpenCV::OnThreadUpdateQueue)

but there is still an error :
error C2440: 'static_cast' : impossible de convertir de 'void (__thiscall IHMOpenCV::* )(wxThreadEvent &)' en 'wxCommandEventFunction'
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19162
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxQueueEvent and thread

Post by doublemax »

Change IHMOpenCV::OnThreadUpdateQueue to take wxThreadEvent instead of wxCommandEvent as parameter.
Use the source, Luke!
Laurent Berger
Earned some good credits
Earned some good credits
Posts: 138
Joined: Tue May 20, 2008 1:03 pm

Re: wxQueueEvent and thread

Post by Laurent Berger »

doublemax wrote:Change IHMOpenCV::OnThreadUpdateQueue to take wxThreadEvent instead of wxCommandEvent as parameter.
already done in my code.

My code is a copy of this example (http://docs.wxwidgets.org/trunk/classwx_thread.html) where you can find this two lines :
EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyFrame::OnThreadUpdate)
wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent); I don't understand how a commandEvent and threadevent can be similar

Code: Select all

// declare a new type of event, to be used by our MyThread class:
wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent);
wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
class MyFrame;
class MyThread : public wxThread
{
public:
MyThread(MyFrame *handler)
: wxThread(wxTHREAD_DETACHED)
{ m_pHandler = handler }
~MyThread();
protected:
virtual ExitCode Entry();
MyFrame *m_pHandler;
};
class MyFrame : public wxFrame
{
public:
...
~MyFrame()
{
// it's better to do any thread cleanup in the OnClose()
// event handler, rather than in the destructor.
// This is because the event loop for a top-level window is not
// active anymore when its destructor is called and if the thread
// sends events when ending, they won't be processed unless
// you ended the thread from OnClose.
// See @ref overview_windowdeletion for more info.
}
...
void DoStartThread();
void DoPauseThread();
// a resume routine would be nearly identic to DoPauseThread()
void DoResumeThread() { ... }
void OnThreadUpdate(wxThreadEvent&);
void OnThreadCompletion(wxThreadEvent&);
void OnClose(wxCloseEvent&);
protected:
MyThread *m_pThread;
wxCriticalSection m_pThreadCS; // protects the m_pThread pointer
friend class MyThread; // allow it to access our m_pThread
wxDECLARE_EVENT_TABLE();
};
wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
EVT_CLOSE(MyFrame::OnClose)
EVT_MENU(Minimal_Start, MyFrame::DoStartThread)
EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyFrame::OnThreadUpdate)
EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_COMPLETED, MyFrame::OnThreadCompletion)
wxEND_EVENT_TABLE()
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_COMPLETED, wxThreadEvent)
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent)
void MyFrame::DoStartThread()
{
m_pThread = new MyThread(this);
if ( m_pThread->Run() != wxTHREAD_NO_ERROR )
{
wxLogError("Can't create the thread!");
delete m_pThread;
m_pThread = NULL;
}
// after the call to wxThread::Run(), the m_pThread pointer is "unsafe":
// at any moment the thread may cease to exist (because it completes its work).
// To avoid dangling pointers OnThreadExit() will set m_pThread
// to NULL when the thread dies.
}
wxThread::ExitCode MyThread::Entry()
{
while (!TestDestroy())
{
// ... do a bit of work...
wxQueueEvent(m_pHandler, new wxThreadEvent(wxEVT_COMMAND_MYTHREAD_UPDATE));
}
// signal the event handler that this thread is going to be destroyed
// NOTE: here we assume that using the m_pHandler pointer is safe,
// (in this case this is assured by the MyFrame destructor)
wxQueueEvent(m_pHandler, new wxThreadEvent(wxEVT_COMMAND_MYTHREAD_COMPLETED));
return (wxThread::ExitCode)0; // success
}
MyThread::~MyThread()
{
wxCriticalSectionLocker enter(m_pHandler->m_pThreadCS);
// the thread is being destroyed; make sure not to leave dangling pointers around
m_pHandler->m_pThread = NULL;
}
void MyFrame::OnThreadCompletion(wxThreadEvent&)
{
wxMessageOutputDebug().Printf("MYFRAME: MyThread exited!\n");
}
void MyFrame::OnThreadUpdate(wxThreadEvent&)
{
wxMessageOutputDebug().Printf("MYFRAME: MyThread update...\n");
}
void MyFrame::DoPauseThread()
{
// anytime we access the m_pThread pointer we must ensure that it won't
// be modified in the meanwhile; since only a single thread may be
// inside a given critical section at a given time, the following code
// is safe:
wxCriticalSectionLocker enter(m_pThreadCS);
if (m_pThread) // does the thread still exist?
{
// without a critical section, once reached this point it may happen
// that the OS scheduler gives control to the MyThread::Entry() function,
// which in turn may return (because it completes its work) making
// invalid the m_pThread pointer
if (m_pThread->Pause() != wxTHREAD_NO_ERROR )
wxLogError("Can't pause the thread!");
}
}
void MyFrame::OnClose(wxCloseEvent&)
{
{
wxCriticalSectionLocker enter(m_pThreadCS);
if (m_pThread) // does the thread still exist?
{
wxMessageOutputDebug().Printf("MYFRAME: deleting thread");
if (m_pThread->Delete() != wxTHREAD_NO_ERROR )
wxLogError("Can't delete the thread!");
}
} // exit from the critical section to give the thread
// the possibility to enter its destructor
// (which is guarded with m_pThreadCS critical section!)
while (1)
{
{ // was the ~MyThread() function executed?
wxCriticalSectionLocker enter(m_pThreadCS);
if (!m_pThread) break;
}
// wait for thread completion
wxThread::This()->Sleep(1);
}
Destroy();
}
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19162
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxQueueEvent and thread

Post by doublemax »

Code: Select all

EVT_COMMAND(wxID_ANY, wxEVT_COMMAND_MYTHREAD_UPDATE, MyFrame::OnThreadUpdate)
Try EVT_THREAD instead of EVT_COMMAND.
Use the source, Luke!
Laurent Berger
Earned some good credits
Earned some good credits
Posts: 138
Joined: Tue May 20, 2008 1:03 pm

Re: wxQueueEvent and thread

Post by Laurent Berger »

the source code now is for IMHVideoimage.cpp

Code: Select all

#include "IHMVideoImage.h"

wxBEGIN_EVENT_TABLE(IHMVideoImage, wxFrame)
    EVT_ERASE_BACKGROUND(IHMVideoImage::OnEraseBackground)
    EVT_PAINT(IHMVideoImage::OnPaint)
	EVT_CLOSE(IHMVideoImage::OnClose)
    EVT_MENU(wxID_ZOOM_IN, IHMVideoImage::OnZoom)
    EVT_MENU(wxID_ZOOM_OUT, IHMVideoImage::OnZoom)
    EVT_MENU(wxID_ZOOM_100, IHMVideoImage::OnZoom)
wxEND_EVENT_TABLE()

#define __QUEUE_EVENT__

#ifdef __QUEUE_EVENT__
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
#endif


#include "wxOpenCV.h"

#include "opencv2/opencv.hpp"

using namespace cv;

wxThread::ExitCode CaptureVideo::Entry()
{
#ifdef __QUEUE_EVENT__
		int i=wxEVT_COMMAND_MYTHREAD_UPDATE;
#endif
	cap= new VideoCapture(0); 
if(!cap->isOpened())  // check if we succeeded
        return  (wxThread::ExitCode)0;  
Mat edges; 
for(;!TestDestroy();)
    {
       Mat frame;
       (*cap) >> frame; // get a new frame from camera

		accesBitmap.Lock();
		unsigned char *pImage=image->GetData();
		unsigned char *pFrame=frame.data;
		int pasLigne=frame.step;
		for (int i=0;i<frame.rows;i++,pFrame+=pasLigne)
		{
			unsigned char *p=pFrame;
			for (int j=0;j<frame.cols;j++)
			{
				pImage[2]=*p++;
				pImage[1]=*p++;
				pImage[0]=*p++;
				pImage+=3;
			}

			
		}
		accesBitmap.Unlock();
#ifdef __QUEUE_EVENT__
		wxQueueEvent( parent->GetEventHandler(), new wxThreadEvent(wxEVT_THREAD,1+(int)wxEVT_COMMAND_MYTHREAD_UPDATE));
#else
        wxCommandEvent *evt = new wxCommandEvent( wxEVT_COMMAND_TEXT_UPDATED, 28 );
        evt->SetInt(39);  // pass some data along the event, a number in this case
        parent->GetEventHandler()->AddPendingEvent( *evt );
#endif
    }
delete cap;
cap=NULL;
return (wxThread::ExitCode)0;  
}
and for main.cpp

Code: Select all

#include "wxOpenCV.h"
#include "opencv2/opencv.hpp"
#include <opencv/highgui.h>
#include "IHMImage.h"
#include "IHMVideoImage.h"

#include <fstream>
#include <map>

using namespace cv;


using namespace std;

enum
{
  // Identifiant des menus
  IHMOpenCV_QUIT = wxID_EXIT,
  IHMOpenCV_APROPOS = wxID_ABOUT,
  IHMOpenCV_DBACQ

};

#define __QUEUE_EVENT__

#ifdef __QUEUE_EVENT__
wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
#endif

// --------------------------------------------------------------------------
// Table des évènements
// --------------------------------------------------------------------------

wxBEGIN_EVENT_TABLE(IHMOpenCV, wxFrame)
  EVT_MENU(IHMOpenCV_QUIT,  IHMOpenCV::OnQuit)
  EVT_MENU(IHMOpenCV_APROPOS, IHMOpenCV::OnAbout)
  EVT_COMMAND(28, wxEVT_COMMAND_TEXT_UPDATED, IHMOpenCV::OnThreadUpdate)
  EVT_MENU(IHMOpenCV_DBACQ, IHMOpenCV::DebutAcq)
#ifdef __QUEUE_EVENT__
  EVT_THREAD(wxEVT_COMMAND_MYTHREAD_UPDATE, IHMOpenCV::OnThreadUpdateQueue)
#endif
  EVT_TIMER(wxID_ANY,IHMOpenCV::OnTimerEvent)
wxEND_EVENT_TABLE()

IMPLEMENT_APP(wxOpenCV)


void IHMOpenCV::OnThreadUpdateQueue(wxThreadEvent &w)
{
// Une nouvelle image doit être affichée
if (!imageVideo)
	return;
nbImageParSeconde++;
// Blocage de l'accés par wxMutex à la mémoire de l'image
imageVideo->accesBitmap.Lock();
// affichage de l'image
ecranVideo->Draw(imageVideo->image);
// Libére l'accès à la mémoire
imageVideo->accesBitmap.Unlock();

}
and I can see video with 30 frames per second. But I have to say that I had modified :
wxQueueEvent( parent->GetEventHandler(), new wxThreadEvent(wxEVT_THREAD,wxEVT_COMMAND_MYTHREAD_UPDATE));
in
wxQueueEvent( parent->GetEventHandler(), new wxThreadEvent(wxEVT_THREAD,1+(int)wxEVT_COMMAND_MYTHREAD_UPDATE));

The reason is written in http://wiki.wxwidgets.org/Custom_Events :
What could possibly go wrong?

You must define the wxEventType exactly once. If you add wxDEFINE_EVENT(MY_NEW_TYPE, wxCommandEvent); to two files, it will be defined twice with two different values. The same thing will happen if you write it only once, but you put it in a header file that is #included more than once. Why does that matter? Because you'll be posting an event with the type (e.g.) 12000, and trying to catch events with type 12001; which will silently fail.
How avoid this? call a method that will be the good value for the event handler...
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19162
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: wxQueueEvent and thread

Post by doublemax »

Like i wrote in a previous post, the wxDEFINE_EVENT(...) line must exist only once and in a .CPP file.
Use the source, Luke!
Laurent Berger
Earned some good credits
Earned some good credits
Posts: 138
Joined: Tue May 20, 2008 1:03 pm

Re: wxQueueEvent and thread

Post by Laurent Berger »

Thanks !
you are right Everything is Ok now
in main.cpp :

Code: Select all

#include "opencv2/opencv.hpp"
#include <opencv/highgui.h>
#include "IHMImage.h"
#include "IHMVideoImage.h"

#include <fstream>
#include <map>

using namespace cv;


using namespace std;

enum
{
  // Identifiant des menus
  IHMOpenCV_QUIT = wxID_EXIT,
  IHMOpenCV_APROPOS = wxID_ABOUT,
  IHMOpenCV_DBACQ

};

wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);
wxDEFINE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);

// --------------------------------------------------------------------------
// Table des évènements
// --------------------------------------------------------------------------

wxBEGIN_EVENT_TABLE(IHMOpenCV, wxFrame)
  EVT_MENU(IHMOpenCV_QUIT,  IHMOpenCV::OnQuit)
  EVT_MENU(IHMOpenCV_APROPOS, IHMOpenCV::OnAbout)
  EVT_MENU(IHMOpenCV_DBACQ, IHMOpenCV::DebutAcq)
  EVT_THREAD(wxEVT_COMMAND_MYTHREAD_UPDATE, IHMOpenCV::OnThreadUpdateQueue)
  EVT_TIMER(wxID_ANY,IHMOpenCV::OnTimerEvent)
wxEND_EVENT_TABLE()

IMPLEMENT_APP(wxOpenCV)


void IHMOpenCV::OnThreadUpdateQueue(wxThreadEvent &w)
{
// Une nouvelle image doit être affichée
if (!imageVideo)
	return;
nbImageParSeconde++;
// Blocage de l'accés par wxMutex à la mémoire de l'image
imageVideo->accesBitmap.Lock();
// affichage de l'image
ecranVideo->Draw(imageVideo->image);
// Libére l'accès à la mémoire
imageVideo->accesBitmap.Unlock();

}

and in IHMVideoImage.cpp

Code: Select all

#include "IHMVideoImage.h"

wxBEGIN_EVENT_TABLE(IHMVideoImage, wxFrame)
    EVT_ERASE_BACKGROUND(IHMVideoImage::OnEraseBackground)
    EVT_PAINT(IHMVideoImage::OnPaint)
	EVT_CLOSE(IHMVideoImage::OnClose)
    EVT_MENU(wxID_ZOOM_IN, IHMVideoImage::OnZoom)
    EVT_MENU(wxID_ZOOM_OUT, IHMVideoImage::OnZoom)
    EVT_MENU(wxID_ZOOM_100, IHMVideoImage::OnZoom)
wxEND_EVENT_TABLE()

wxDECLARE_EVENT(wxEVT_COMMAND_MYTHREAD_UPDATE, wxThreadEvent);


#include "wxOpenCV.h"

#include "opencv2/opencv.hpp"

using namespace cv;
wxThread::ExitCode CaptureVideo::Entry()
{
	cap= new VideoCapture(0); 
if(!cap->isOpened())  // check if we succeeded
        return  (wxThread::ExitCode)0;  
Mat edges; 
for(;!TestDestroy();)
    {
       Mat frame;
       (*cap) >> frame; // get a new frame from camera

		accesBitmap.Lock();
		unsigned char *pImage=image->GetData();
		unsigned char *pFrame=frame.data;
		int pasLigne=frame.step;
		for (int i=0;i<frame.rows;i++,pFrame+=pasLigne)
		{
			unsigned char *p=pFrame;
			for (int j=0;j<frame.cols;j++)
			{
				pImage[2]=*p++;
				pImage[1]=*p++;
				pImage[0]=*p++;
				pImage+=3;
			}

			
		}
		accesBitmap.Unlock();
		wxQueueEvent( parent->GetEventHandler(), new wxThreadEvent(wxEVT_THREAD,wxEVT_COMMAND_MYTHREAD_UPDATE));
    }
delete cap;
cap=NULL;
return (wxThread::ExitCode)0;  
}

L.B.
Post Reply