Help on Multi-Threaded applicaiton [modified]
-
I tired to implement using SetEvent, but it still deadlocks, as I dont see any processor activity at all and just a busy mouse icon on the application interface. Here is how I did it - I defined the event handles at the start of the application in your way rather than using CEvent objects like I did before
getnewframe = ::CreateEvent(NULL, FALSE, FALSE, NULL);
newframeevent = ::CreateEvent(NULL, FALSE, FALSE, NULL);when the user clicks snapshot, I call a function (snapshot)
snapshot(exposure)
{
set camera exposure
start snapshotthread if not running
SetEvent(getnewframe)
::WaitForSingleObject(waitfornewframe, INFINITE);
display the frame
}
.
.
.
camthread
{
do
{
::WaitForSingleObject(getnewframe, INFINITE);
take a 20ms snapshot
SetEvent(waitfornewframe);
}while(camrunning)
}I still dont get where I am doing wrong :confused:. I even tried using a while loop in snapshot function and using a 1ms timeout value for WaitForSingleObject and checking for WAIT_OBJECT_0.
PKNT
I'm not seeing a deadlock situation in the pseudo code... If you run it in the debugger and break, are both threads sitting in the Wait function? If so, why?
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I'm not seeing a deadlock situation in the pseudo code... If you run it in the debugger and break, are both threads sitting in the Wait function? If so, why?
Mark Salsbery Microsoft MVP - Visual C++ :java:
Here is what happening in debug more
snapshot(exposure)
{
set camera exposure
start snapshotthread if not running
SetEvent(getnewframe)
::WaitForSingleObject(waitfornewframe, INFINITE); -- set breakpoint(1)
display the frame
}
.
.
.
camthread
{
do
{
dummy variable -- set breakpoint(2)
::WaitForSingleObject(getnewframe, INFINITE);
take a 20ms snapshot
SetEvent(waitfornewframe);
}while(camrunning)
}when I hit snapshot button, the program stops at breakpoint(1) and then goes to breakpoint(2) and thats it from there it does nothing while the C++ interface shows as the program is in [run] mode. From the definitions of SetEvent and WaitForSingleObject I too dont see any thing wrong here. Do they need to be in actual two different threads, I dont think thats the case, interesting!
PKNT
-
Here is what happening in debug more
snapshot(exposure)
{
set camera exposure
start snapshotthread if not running
SetEvent(getnewframe)
::WaitForSingleObject(waitfornewframe, INFINITE); -- set breakpoint(1)
display the frame
}
.
.
.
camthread
{
do
{
dummy variable -- set breakpoint(2)
::WaitForSingleObject(getnewframe, INFINITE);
take a 20ms snapshot
SetEvent(waitfornewframe);
}while(camrunning)
}when I hit snapshot button, the program stops at breakpoint(1) and then goes to breakpoint(2) and thats it from there it does nothing while the C++ interface shows as the program is in [run] mode. From the definitions of SetEvent and WaitForSingleObject I too dont see any thing wrong here. Do they need to be in actual two different threads, I dont think thats the case, interesting!
PKNT
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
I even tired that too by commenting it out, but it does the same. will keep tryin different ways and see. Do you think I may need to define those event handles in CMutex objects :~ .
PKNT
-
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
does it matter how I am defining my thread?? I am using DWORD WINAPI camclass::camthread(LPVOID) form.
PKNT
-
I even tired that too by commenting it out, but it does the same. will keep tryin different ways and see. Do you think I may need to define those event handles in CMutex objects :~ .
PKNT
Kiran Satish wrote:
Do you think I may need to define those event handles in CMutex objects
No that's a different type of synchronization object for mutual exclusion.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
does it matter how I am defining my thread?? I am using DWORD WINAPI camclass::camthread(LPVOID) form.
PKNT
How are you creating your threads? If you're using MFC and using MFC class objects in your threads you should be using AfxBeginThread(), and the prototype for the thread proc is UINT __cdecl ThreadProc(LPVOID pParam); If you're not using MFC but using CRT functions anywhere in your threads (including new/delete!) then you should be using _beginthread() or _beginthreadex(), and the prototype for the thread proc is unsigned __stdcall ThreadProc(void *lpParameter); For a pure C/C++ thread on Windows which doesn't use MFC or the CRT, you can use ::CreateThread(), and the prototype for the thread proc is DWORD WINAPI ThreadProc(LPVOID lpParameter); For MFC and/or CRT, make sure you're linking to the multithread version of those libraries.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
hmm the only reason I see that could happen is if "take a 20ms snapshot" never returns so the waitfornewframe event gets set.
Mark Salsbery Microsoft MVP - Visual C++ :java:
I got it running. Unfortunately it doesnt run when I do it the way we discussed earlier, but when I run it in two different threads it works like it should. I am not sure why it did like tht before, but it doesnt work when I have it in between a function and thread.
PKNT
-
I got it running. Unfortunately it doesnt run when I do it the way we discussed earlier, but when I run it in two different threads it works like it should. I am not sure why it did like tht before, but it doesnt work when I have it in between a function and thread.
PKNT
I always thought it was two threads!
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I always thought it was two threads!
Mark Salsbery Microsoft MVP - Visual C++ :java:
Sorry abt that confusion... maybe I wasnt clear enough.... :), anyway now I know how to use Events in an efficent way... thanks for your help and patience on this...
PKNT
-
Sorry abt that confusion... maybe I wasnt clear enough.... :), anyway now I know how to use Events in an efficent way... thanks for your help and patience on this...
PKNT
Kiran Satish wrote:
maybe I wasnt clear enough
I think I just assumed :) Glad you got it working! Cheers, mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Cool good luck! Keep in mind: Locking is bad - eliminate it if possible - only lock for as long as necessary, and there's lots of other threads running in the system to mess with your timing :) Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
I am back with another issue in this application :) , saving frames in real-time without dropping and in the same order. I tried using BipBuffer[^]. This is how I implemented, the actual thread keeps running and signals an event to 'SaveImage' thread for every ~20msec where it appends the image data to BipBuffer memory while another thread keeps running all the time saving images from BipBuffer until the BipBuffer memory is NULL. I am allocating 64x(512x512)bytes of memory to BipBuffer. While running like this, the close loop (main thread) starts off at 50Hz and after a while (like 6-7 sec) depending on the size of BipBuffer memory, it slows down to like 39Hz and then goes back to 50Hz slowly. Is there any other way I can save all the images in real-time at 50Hz with out dropping the actual frames coming in from the camera (i.e I have ~17msec to save a particular frame)?? -thanks
PKNT
-
I am back with another issue in this application :) , saving frames in real-time without dropping and in the same order. I tried using BipBuffer[^]. This is how I implemented, the actual thread keeps running and signals an event to 'SaveImage' thread for every ~20msec where it appends the image data to BipBuffer memory while another thread keeps running all the time saving images from BipBuffer until the BipBuffer memory is NULL. I am allocating 64x(512x512)bytes of memory to BipBuffer. While running like this, the close loop (main thread) starts off at 50Hz and after a while (like 6-7 sec) depending on the size of BipBuffer memory, it slows down to like 39Hz and then goes back to 50Hz slowly. Is there any other way I can save all the images in real-time at 50Hz with out dropping the actual frames coming in from the camera (i.e I have ~17msec to save a particular frame)?? -thanks
PKNT
Kiran Satish wrote:
I am allocating 64x(512x512)bytes of memory to BipBuffer
Are you sure that's a big enough buffer? If the data is 24bpp RGB, you may want 64x(512x512x3). Which thread is slowing down? Are you locking something (or staying in a critical section) too long? Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Kiran Satish wrote:
I am allocating 64x(512x512)bytes of memory to BipBuffer
Are you sure that's a big enough buffer? If the data is 24bpp RGB, you may want 64x(512x512x3). Which thread is slowing down? Are you locking something (or staying in a critical section) too long? Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
My images are only 8bpp(0-255) and I use unsigned char pointer for image data. I am not sure which thread is slowing down and as fas as I know I dont have any critical sections. Here is the order- BipBuffer ImageBuffer; ImageBuffer.AllocateBuffer(128*m_FrameBufferSize) //m_FrameBufferSize = 512x512 -Main Thread (camera thread)- // this controls the processing thread while (camthread) take image (~20.5msec) copy image data into shared buffer set event to processing thread -Processing thread- while (processing thread) wait for event from camera copy image data from shared buffer to processing buffer if(saveimage) copy image data from shared buffer to buffer for saving image Set event to save image thread do the processing on image data in processing buffer Update displays for results -Save Image thread- BYTE* pData wait for save image event pData = ImageBuffer.Reserve(m_FrameBufferSize, iResult) memcpy(pData, m_pImageBuffer, iResult) ImageBuffer.Commit(iResult) //iResult will be equal to m_FrameBufferSize -Store Image thread- //this thread runs continuously until BipBuffer == NULL while ((pData = ImageBuffer.GetContiguousBlock(iResult)) != NULL){ create filename write image data to a file (I tried writing in two ways to see if there will be any difference in speed, one as a tiff format and also as a binary file) ImageBuffer.DecommitBlock(iResult)} I think I might just use a standard circular buffer of my own rather than BipBuffer as I see there is something going on when using it. When I run the program loop for 15sec, the number of images being stored are increasing from one run to another. Hope I am clear :) . If I comment out writing image data to a file in store image thread, everything runs fine at desired speed. -thanks
PKNT
-
Kiran Satish wrote:
I am allocating 64x(512x512)bytes of memory to BipBuffer
Are you sure that's a big enough buffer? If the data is 24bpp RGB, you may want 64x(512x512x3). Which thread is slowing down? Are you locking something (or staying in a critical section) too long? Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
Also I did a test with 5sec, the camera is indeed getting all the frames (5000/20.5 = ~243) constantly, while using BipBuffer and saving the images, for first run I get ~206 saved, second run ~213, third run ~224 etc, which I think is overwriting the frame data in the buffer, but the difference in the numbers doesnt explain anything to me. There should be a pretty simple way to write data to HDD at 50frames/sec (at 512x512bytes/frame), which I dont think is that much when you consider real-time applications :confused:.
PKNT
-
My images are only 8bpp(0-255) and I use unsigned char pointer for image data. I am not sure which thread is slowing down and as fas as I know I dont have any critical sections. Here is the order- BipBuffer ImageBuffer; ImageBuffer.AllocateBuffer(128*m_FrameBufferSize) //m_FrameBufferSize = 512x512 -Main Thread (camera thread)- // this controls the processing thread while (camthread) take image (~20.5msec) copy image data into shared buffer set event to processing thread -Processing thread- while (processing thread) wait for event from camera copy image data from shared buffer to processing buffer if(saveimage) copy image data from shared buffer to buffer for saving image Set event to save image thread do the processing on image data in processing buffer Update displays for results -Save Image thread- BYTE* pData wait for save image event pData = ImageBuffer.Reserve(m_FrameBufferSize, iResult) memcpy(pData, m_pImageBuffer, iResult) ImageBuffer.Commit(iResult) //iResult will be equal to m_FrameBufferSize -Store Image thread- //this thread runs continuously until BipBuffer == NULL while ((pData = ImageBuffer.GetContiguousBlock(iResult)) != NULL){ create filename write image data to a file (I tried writing in two ways to see if there will be any difference in speed, one as a tiff format and also as a binary file) ImageBuffer.DecommitBlock(iResult)} I think I might just use a standard circular buffer of my own rather than BipBuffer as I see there is something going on when using it. When I run the program loop for 15sec, the number of images being stored are increasing from one run to another. Hope I am clear :) . If I comment out writing image data to a file in store image thread, everything runs fine at desired speed. -thanks
PKNT
Kiran Satish wrote:
I think I might just use a standard circular buffer of my own rather than BipBuffer as I see there is something going on when using it.
I think that's a good place to start. I use simple queues (FIFO) with good results. Use preallocated buffers, and design them so they can work with the queue with as little blocking synchrnization as possible. Also try to eliminate copying the frame data so many times (~13MB/sec for each!) - it looks like every thread does a copy. If any threads can share the same copy, that will be much more efficient.
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
Kiran Satish wrote:
I think I might just use a standard circular buffer of my own rather than BipBuffer as I see there is something going on when using it.
I think that's a good place to start. I use simple queues (FIFO) with good results. Use preallocated buffers, and design them so they can work with the queue with as little blocking synchrnization as possible. Also try to eliminate copying the frame data so many times (~13MB/sec for each!) - it looks like every thread does a copy. If any threads can share the same copy, that will be much more efficient.
Mark Salsbery Microsoft MVP - Visual C++ :java:
I did some more tests and came to a conclusion that writing data to HDD is the only thing thats slowing down the loop randomly. Sometimes it wont and sometimes it does, very random, but most of the time its slows down and then gets back, doesnt matter if its FIFO structure or using fixed memory allocation. I did take out save image thread and copying image data directly into FIFO buffer (this is because I want to keep all the images in sequence without dropping any irrespective of the speed of writing thread) within the processing thread while using only one store image thread where the actual writing to HDD takes place from FIFO. Again, if I comment out just one line of writing data to HDD, everything works fine. Just for the Info, I have two 7.2k rpm SATA drives in RAID1. The only solution I think of for now is, save the images in a big block of memory and write them to HDD once the loop is stopped, ofcourse this is not at all efficient way to go with and we can't run the loop for ever or to say there will be a limit of ~22sec continuous run.
PKNT
-
My images are only 8bpp(0-255) and I use unsigned char pointer for image data. I am not sure which thread is slowing down and as fas as I know I dont have any critical sections. Here is the order- BipBuffer ImageBuffer; ImageBuffer.AllocateBuffer(128*m_FrameBufferSize) //m_FrameBufferSize = 512x512 -Main Thread (camera thread)- // this controls the processing thread while (camthread) take image (~20.5msec) copy image data into shared buffer set event to processing thread -Processing thread- while (processing thread) wait for event from camera copy image data from shared buffer to processing buffer if(saveimage) copy image data from shared buffer to buffer for saving image Set event to save image thread do the processing on image data in processing buffer Update displays for results -Save Image thread- BYTE* pData wait for save image event pData = ImageBuffer.Reserve(m_FrameBufferSize, iResult) memcpy(pData, m_pImageBuffer, iResult) ImageBuffer.Commit(iResult) //iResult will be equal to m_FrameBufferSize -Store Image thread- //this thread runs continuously until BipBuffer == NULL while ((pData = ImageBuffer.GetContiguousBlock(iResult)) != NULL){ create filename write image data to a file (I tried writing in two ways to see if there will be any difference in speed, one as a tiff format and also as a binary file) ImageBuffer.DecommitBlock(iResult)} I think I might just use a standard circular buffer of my own rather than BipBuffer as I see there is something going on when using it. When I run the program loop for 15sec, the number of images being stored are increasing from one run to another. Hope I am clear :) . If I comment out writing image data to a file in store image thread, everything runs fine at desired speed. -thanks
PKNT
If I'm reading this correctly, and you've got two threads running, you might need to add some critical sections or events around your use of the BipBuffer; as the code stands it's not threadsafe.