GUI blocked after using 3 wxThread

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

GUI blocked after using 3 wxThread

Post by Laurent Berger »

Hi,

I have got a program which display image from usb webcam. I can display two webcam image without problem (using wxthread sending event to GUI). When I want to open 3 webcam GUI is blocked or very slow (with four webcam GUI is blocked) but program is still running using only 8% of cpu. I think something is wrong in my program.

In wxThread I use those lines to send event to GUI with a critical section :

Code: Select all

		 while(attendre && nbBoucle<100)
		{
			if (!parent)
				break;
                        {
                         wxCriticalSectionLocker enter(((FenetrePrincipale*)parent)->travailCam);
			  if (((FenetrePrincipale*)parent)->IndEvtCam()==indEvt-1 || nbBoucle==99)
			  {
                                 EvtPointSuivis *x = new EvtPointSuivis(VAL_EVT_PTS_SUIVIS);
                            	x->ptId = repereIni;
                           	 x->ptApp = repere;
                            	x->SetTimestamp(wxGetUTCTimeMillis().GetLo());
                            	x->indEvt = indEvt;
                            	indEvt++;
                            	wxQueueEvent( ((FenetrePrincipale*)parent)->GetEventHandler(), x);
				attendre=false;
			 }
			 }
			nbBoucle++;
			if (attendre)this->Sleep(1);
		}

In main thread (GUI) i have something like this :

Code: Select all

void FenetrePrincipale::OnThreadUpdateQueue(EvtPointSuivis &w)
{

if (cam && (cam->IsRunning() || cam->IsPaused()))
	{
	long x=wxGetUTCTimeMillis().GetLo();
	{
	wxCriticalSectionLocker enter(travailCam);

	delete feuille->BitmapAffichee();
	feuille->BitmapAffichee(NULL);
        DIB(imAcq);
	feuille->Refresh(false);
	}
	indEvtCam=w.indEvt;
	nbImageCam++;
	if (nbImageCam==25)
		{
		cam->DefTpsInactif((x - tpsPreEvt) / 25);
		nbImageCam=0;
		tpsPreEvt=x;
		
		osgApp->CtrlCamera()->DrawOngletStatus();
		}
    }
return;
}

Any help would be appreciated.
Thanks in advance
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GUI blocked after using 3 wxThread

Post by doublemax »

Does each thread have its own parent window or do they all send their event to the same one?

How is the actual image data transferred?
What's the frequency of these events?
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: GUI blocked after using 3 wxThread

Post by Laurent Berger »

Each thread have its own parent window. each window have its own critical section too.
Image is grabbed in memory and an event is send to main thread(GUI). Main thread used a critical section to transfer data to wxImage (and hence thread cannot grabbed a new image )

frequency is 30 event per second (capture image frequency)
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GUI blocked after using 3 wxThread

Post by doublemax »

Which platform and which CPU do you have?
What's the resolution of the images?

I can't spot anything wrong in the code, but my guess is that the main thread is overloaded. If you have a 8-core cpu, it could show as 8% total cpu load although the main thread is almost at 100%.

If the frame rate is 30fps, why do you Sleep() for 1ms? Will you get a new image from the camera right away? What happens if you increase the duration a bit?
Use the source, Luke!
Manolo
Can't get richer than this
Can't get richer than this
Posts: 827
Joined: Mon Apr 30, 2012 11:07 pm

Re: GUI blocked after using 3 wxThread

Post by Manolo »

Multithreaded apps are difficult to debug. Once I had to write in a file a trace for almost each line of code so as to find where code was wrong.
Good luck.
Laurent Berger
Earned some good credits
Earned some good credits
Posts: 138
Joined: Tue May 20, 2008 1:03 pm

Re: GUI blocked after using 3 wxThread

Post by Laurent Berger »

I think I have found bug with your comments
frequency of these events
I am able to open 4 webcams when i fixed frequency 10hz. Then I changed frequency to 30Hz and it works. I think problem was when I open webcam. It takes too much times in main thread (2 or 3 second). It means 60 or 90 events for two webcams. main thread is overloaded. I changed my code in wxThread for webcam :

Code: Select all

				while(attendre && nbBoucle<100)
				{
					if (!parent)
						break;
                    {
                        wxCriticalSectionLocker enter(((FenetrePrincipale*)parent)->travailCam);
					    if (indEvt==0 || ((FenetrePrincipale*)parent)->IndEvtCam()==indEvt-1 /*|| nbBoucle==99*/) // comment here now it means when no answer from gui thread don't send new event
						    {
                            EvtPointSuivis *x = new EvtPointSuivis(VAL_EVT_PTS_SUIVIS);
                            x->ptId = repereIni;
                            x->ptApp = repere;
                            x->SetTimestamp(wxGetUTCTimeMillis().GetLo());
                            x->indEvt = indEvt;
                            indEvt++;
                            wxQueueEvent( ((FenetrePrincipale*)parent)->GetEventHandler(), x);
						    attendre=false;
						    }
					}
					nbBoucle++;
					if (attendre)this->Sleep(1);
				}

About wxSleep it means that main thread does not send acknowledgement for previous event webcam thread sleep 1 ms.
May be it is possible to check how many events are present in file event but I don't know to do.

Thanks for yours helps

Webcam 640x480 grab using opencv (Direct show)
Windows 10 i7-5820K 3.3GHz 16Go
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GUI blocked after using 3 wxThread

Post by doublemax »

I don't know how important a fixed framerate for your application is, but i think you should make the logic more "dynamic". Rather than flooding the main thread with new frames, the main thread should signal when it's ready to process a new thread.

Code: Select all

DIB(imAcq);
I assume this line contains the code that converts the wxImage to a wxBitmap so that you can display it on the screen? This is most likely the part that slows everything down. I know it's usually forbidden to use a wxBitmap in a secondary thread, but the "thread" sample that comes with wxWidgets does just that. Maybe it might be worth a try to move the conversion into the thread.
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: GUI blocked after using 3 wxThread

Post by Laurent Berger »

the main thread should signal when it's ready to process a new thread.
thanks I will try it.
DIB(imAcq);
Yes I convert an[https://github.com/LaurentBerger/wxOpen ... e.cpp#L366] opencv Mat in wxImage[/url]. It's not easy to move function in webcam thread. I will try to improve DIB code using thread.
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GUI blocked after using 3 wxThread

Post by doublemax »

Yes I convert an opencv Mat in wxImage.
Oh dear, i thought you'd get 24bit RGB data from OpenCV and this would just be a wxImage to wxBitmap conversion. Can't you tell OpenCV to return 24Bit RGB data? That would make the conversion much easier.
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: GUI blocked after using 3 wxThread

Post by Laurent Berger »

Unfortunately no. Opencv use BGR format and an explanation is given https://www.learnopencv.com/why-does-op ... or-format/
L.B.
User avatar
doublemax
Moderator
Moderator
Posts: 19114
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: GUI blocked after using 3 wxThread

Post by doublemax »

RGB or BGR wouldn't make any difference, actually it would enable an even faster conversion under Windows where bitmaps use BGR internally, too.

But the code in FenetrePrincipale::DIBImage does a lot more than that. Even if this is all necessary, i'm pretty sure there is lots of room for optimization.
Use the source, Luke!
Post Reply