Multithread and GDI Issues
-
Hi, I like to draw lines with delay but using threads. The data will be fetched from different list (m_lstpoints). they have to be drawn simultaneously. When i tried to do this i am getting illegal. I am very much new to threads. Can u help me. //Code CRITICAL_SECTION g_csGDILock; //Initialized AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo1); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo2); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo3);//This list is dynamic //The pTInfo contains the g_csGDILock pointer and other info //to draw points such as dc and list of points. void CPlotPoints::TDrawPoints(HDC hdc, PRTL_CRITICAL_SECTION pMutex){//Non static POSITION pos =NULL; CPoint pt1, pt2; pos =m_lstPoints.GetHeadPosition(); pt1=(CPoint) m_lstPoints.GetNext(pos); while (pos){ EnterCriticalSection(pMutex); { pt2=(CPoint) m_lstPoints.GetNext(pos); CDC dc; //hdc is a CClientDC dc.Attach(hdc);//I had even tried to Send CClientDC* directly //Plot code begins //Here we draw rectangles,lines or something using dc //dc.Moveto(pt1); //These lines are giving assertion //Plot code ends here dc.Detach(); GdiFlush(); } LeaveCriticalSection(pMutex); Sleep(300); } } Thank you. Manu
-
Hi, I like to draw lines with delay but using threads. The data will be fetched from different list (m_lstpoints). they have to be drawn simultaneously. When i tried to do this i am getting illegal. I am very much new to threads. Can u help me. //Code CRITICAL_SECTION g_csGDILock; //Initialized AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo1); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo2); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo3);//This list is dynamic //The pTInfo contains the g_csGDILock pointer and other info //to draw points such as dc and list of points. void CPlotPoints::TDrawPoints(HDC hdc, PRTL_CRITICAL_SECTION pMutex){//Non static POSITION pos =NULL; CPoint pt1, pt2; pos =m_lstPoints.GetHeadPosition(); pt1=(CPoint) m_lstPoints.GetNext(pos); while (pos){ EnterCriticalSection(pMutex); { pt2=(CPoint) m_lstPoints.GetNext(pos); CDC dc; //hdc is a CClientDC dc.Attach(hdc);//I had even tried to Send CClientDC* directly //Plot code begins //Here we draw rectangles,lines or something using dc //dc.Moveto(pt1); //These lines are giving assertion //Plot code ends here dc.Detach(); GdiFlush(); } LeaveCriticalSection(pMutex); Sleep(300); } } Thank you. Manu
-
Hi, I like to draw lines with delay but using threads. The data will be fetched from different list (m_lstpoints). they have to be drawn simultaneously. When i tried to do this i am getting illegal. I am very much new to threads. Can u help me. //Code CRITICAL_SECTION g_csGDILock; //Initialized AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo1); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo2); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo3);//This list is dynamic //The pTInfo contains the g_csGDILock pointer and other info //to draw points such as dc and list of points. void CPlotPoints::TDrawPoints(HDC hdc, PRTL_CRITICAL_SECTION pMutex){//Non static POSITION pos =NULL; CPoint pt1, pt2; pos =m_lstPoints.GetHeadPosition(); pt1=(CPoint) m_lstPoints.GetNext(pos); while (pos){ EnterCriticalSection(pMutex); { pt2=(CPoint) m_lstPoints.GetNext(pos); CDC dc; //hdc is a CClientDC dc.Attach(hdc);//I had even tried to Send CClientDC* directly //Plot code begins //Here we draw rectangles,lines or something using dc //dc.Moveto(pt1); //These lines are giving assertion //Plot code ends here dc.Detach(); GdiFlush(); } LeaveCriticalSection(pMutex); Sleep(300); } } Thank you. Manu
Several remarks first: - You don't describe which problem you are having: "i am getting illegal" is not very informative sentence to me :~ - Use the pre tags to format your code properly because it is almost unreadable. - Please, read the posting guidelines on top of this forum. Now for your problem: if you are trying to draw things from multiple threads, that's probably why your code crashes. You should only have the main thread that access the UI.
Cédric Moonen Software developer
Charting control [v1.3 - Updated] -
Several remarks first: - You don't describe which problem you are having: "i am getting illegal" is not very informative sentence to me :~ - Use the pre tags to format your code properly because it is almost unreadable. - Please, read the posting guidelines on top of this forum. Now for your problem: if you are trying to draw things from multiple threads, that's probably why your code crashes. You should only have the main thread that access the UI.
Cédric Moonen Software developer
Charting control [v1.3 - Updated]Sir, You got it. I am sorry to say this that i mentioned in the code with a comment where i am getting illegal or assertion dailog. ("//dc.Moveto(pt1); //These lines are giving assertion"). I am clearly and purposefully making my child threads to draw the lines. What is the alternative. More over i had initialized the critical section also. 1. Shall i ask the view to redraw the points by sending the points 2. or else i have to do something else. Thanks for answering my question. Regards, Manu
-
Sir, You got it. I am sorry to say this that i mentioned in the code with a comment where i am getting illegal or assertion dailog. ("//dc.Moveto(pt1); //These lines are giving assertion"). I am clearly and purposefully making my child threads to draw the lines. What is the alternative. More over i had initialized the critical section also. 1. Shall i ask the view to redraw the points by sending the points 2. or else i have to do something else. Thanks for answering my question. Regards, Manu
kanduripavan wrote:
1. Shall i ask the view to redraw the points by sending the points
Yes, you should find a mechanism that let the view (and only the view) redraw the data? Everything that is 'generated' from the threads should be independant from the view. You'll need to store this data somewhere and inform the view that new data is available by sending a message to the view. Access to the data should also be protected with critical sections (for example).
Cédric Moonen Software developer
Charting control [v1.3 - Updated] -
kanduripavan wrote:
1. Shall i ask the view to redraw the points by sending the points
Yes, you should find a mechanism that let the view (and only the view) redraw the data? Everything that is 'generated' from the threads should be independant from the view. You'll need to store this data somewhere and inform the view that new data is available by sending a message to the view. Access to the data should also be protected with critical sections (for example).
Cédric Moonen Software developer
Charting control [v1.3 - Updated]Sir, Thank you very much. I am very much new to threading. I like to plot points without timer and using threads only. The output which i wanted was that each points has to be plotted individually. Nothing professional. i am just entering into this new world of threading and experiencing the problems of multi thread programming if i am going to implement in near future. I will try and implement the same and get back to you. I saw similar kind of codes in MTGDI but they are subclassed(CWinthread). I want to experiment if a particular section of the code is implemented by multiple threads then what will happen.What will happen to CList object poistion variables, and impact of other things. This is my intention. Thank you very much. Manu
-
Hi, I like to draw lines with delay but using threads. The data will be fetched from different list (m_lstpoints). they have to be drawn simultaneously. When i tried to do this i am getting illegal. I am very much new to threads. Can u help me. //Code CRITICAL_SECTION g_csGDILock; //Initialized AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo1); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo2); AfxBeginThread(DrawStrokesUsingThrd, (LPVOID)pTInfo3);//This list is dynamic //The pTInfo contains the g_csGDILock pointer and other info //to draw points such as dc and list of points. void CPlotPoints::TDrawPoints(HDC hdc, PRTL_CRITICAL_SECTION pMutex){//Non static POSITION pos =NULL; CPoint pt1, pt2; pos =m_lstPoints.GetHeadPosition(); pt1=(CPoint) m_lstPoints.GetNext(pos); while (pos){ EnterCriticalSection(pMutex); { pt2=(CPoint) m_lstPoints.GetNext(pos); CDC dc; //hdc is a CClientDC dc.Attach(hdc);//I had even tried to Send CClientDC* directly //Plot code begins //Here we draw rectangles,lines or something using dc //dc.Moveto(pt1); //These lines are giving assertion //Plot code ends here dc.Detach(); GdiFlush(); } LeaveCriticalSection(pMutex); Sleep(300); } } Thank you. Manu
You can do drawing from another thread, but you need to really understand thread synchronization. Nothing in GDI is thread safe, so ALL GDI operations need to be synchronized between threads. Have you initialized your GDI critical section? Do you have one and ONLY one critical section object shared by all the threads? If you answered no to either of those, you aren't using thread synchronization objects correctly. Don't forget to synchronize the UI thread as well. What is causing the assertion? You should be able to look right at the offending line of code in the debugger. What is the exact assertion message? Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
kanduripavan wrote:
1. Shall i ask the view to redraw the points by sending the points
Yes, you should find a mechanism that let the view (and only the view) redraw the data? Everything that is 'generated' from the threads should be independant from the view. You'll need to store this data somewhere and inform the view that new data is available by sending a message to the view. Access to the data should also be protected with critical sections (for example).
Cédric Moonen Software developer
Charting control [v1.3 - Updated]Hi, I did it as you said. It has fixed my problem of plotting multiple points simultaneously.
EnterCriticalSection(pMutex); { pt2=(CPoint) m_lstPoints.GetNext(pos); //CDC dc; //hdc is a CClientDC //dc.Attach(hdc);//I had even tried to Send CClientDC* directly //Plot code begins //Here we draw rectangles,lines or something using dc //dc.Moveto(pt1); //These lines are giving assertion //Plot code ends here //dc.Detach(); //GdiFlush(); //Instead of the above code i used pView->SendMessage(ID_VIEW_DRAWOFFLINE, (LPARAM)&pt1,(WPARAM)&pt2 ); LeaveCriticalSection(pMutex); }
Thank you very much Cédric Moonen, Mark Salsbery,Suman and others who looked after my issue. -
You can do drawing from another thread, but you need to really understand thread synchronization. Nothing in GDI is thread safe, so ALL GDI operations need to be synchronized between threads. Have you initialized your GDI critical section? Do you have one and ONLY one critical section object shared by all the threads? If you answered no to either of those, you aren't using thread synchronization objects correctly. Don't forget to synchronize the UI thread as well. What is causing the assertion? You should be able to look right at the offending line of code in the debugger. What is the exact assertion message? Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
I have one one critical section shared by all the threads. I had Initialized the critical section before creating the child threads. I have 2 doubts. 1.The critical section is initialized by the UI Thread ie by the primary thread. So is it there it can go wrong. 2.Lets leave the GDI issue and consider the handle as a shared object which is inside the critcal section. SO how can the 2nd or the 3rd thread can enter and access it. As a beginner it seems for me that is is not logically valid. (the thread trying to acess gdi handles which is inside the critical section). I am extremely sorry to say these lines. The assertion is shown in GDI files. But as far as i know it occured due to the line dc.LineTo(pt1);//From here onwards the error might have occured I like to thank you for supporting the one who doesnt knows anything. Thank you.
-
Hi, I did it as you said. It has fixed my problem of plotting multiple points simultaneously.
EnterCriticalSection(pMutex); { pt2=(CPoint) m_lstPoints.GetNext(pos); //CDC dc; //hdc is a CClientDC //dc.Attach(hdc);//I had even tried to Send CClientDC* directly //Plot code begins //Here we draw rectangles,lines or something using dc //dc.Moveto(pt1); //These lines are giving assertion //Plot code ends here //dc.Detach(); //GdiFlush(); //Instead of the above code i used pView->SendMessage(ID_VIEW_DRAWOFFLINE, (LPARAM)&pt1,(WPARAM)&pt2 ); LeaveCriticalSection(pMutex); }
Thank you very much Cédric Moonen, Mark Salsbery,Suman and others who looked after my issue.And, It seems to me you are using document view architecture. I understand MFC framework has mechanism for achieving this type of requirement. Have a look at CDocument::UpdateAllViews() and CView::OnUpdate "Typically you should not perform any drawing directly from OnUpdate. Instead, determine the rectangle describing, in device coordinates, the area that requires updating; pass this rectangle to CWnd::InvalidateRect. This causes painting to occur the next time a WM_PAINT message is received." from msdn. This allows all the drawing code happens in WM_PAINT message than custom message. In your thread modify the members of document object which stores the points and call UpdateAllViews(). which finally results WM_PAINT message for the views, in the paint handler of the view get the points from Document object (must be synchronised) and draw the view.
-
I have one one critical section shared by all the threads. I had Initialized the critical section before creating the child threads. I have 2 doubts. 1.The critical section is initialized by the UI Thread ie by the primary thread. So is it there it can go wrong. 2.Lets leave the GDI issue and consider the handle as a shared object which is inside the critcal section. SO how can the 2nd or the 3rd thread can enter and access it. As a beginner it seems for me that is is not logically valid. (the thread trying to acess gdi handles which is inside the critical section). I am extremely sorry to say these lines. The assertion is shown in GDI files. But as far as i know it occured due to the line dc.LineTo(pt1);//From here onwards the error might have occured I like to thank you for supporting the one who doesnt knows anything. Thank you.
kanduripavan wrote:
1.The critical section is initialized by the UI Thread ie by the primary thread. So is it there it can go wrong.
Any thread can initialize it, as long as it's initialized before a thread tries to use it.
kanduripavan wrote:
consider the handle as a shared object which is inside the critcal section
This is only a logical way to think about it. In reality, there's no protection of the handle by the critical section. What the critical section does is prevent execution of code by a thread until another thread owning the critical section releases the critical section. This can be used to prevent two threads from using/changing the same handle/variable/data or any other resource shared by multiple threads. Critical sections can also be used just to prevent two threads from executing the same code simultaneously - there doesn't have to be any data or other resource involved.
kanduripavan wrote:
The assertion is shown in GDI files
You have the source code - what's the line of code?? Using MFC may not work for what you're doing, since MFC has internal containers that are thread-specific. To get around this, you can use an HDC directly instead of through the CDC and derived classes. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I have one one critical section shared by all the threads. I had Initialized the critical section before creating the child threads. I have 2 doubts. 1.The critical section is initialized by the UI Thread ie by the primary thread. So is it there it can go wrong. 2.Lets leave the GDI issue and consider the handle as a shared object which is inside the critcal section. SO how can the 2nd or the 3rd thread can enter and access it. As a beginner it seems for me that is is not logically valid. (the thread trying to acess gdi handles which is inside the critical section). I am extremely sorry to say these lines. The assertion is shown in GDI files. But as far as i know it occured due to the line dc.LineTo(pt1);//From here onwards the error might have occured I like to thank you for supporting the one who doesnt knows anything. Thank you.
I looked at the MFC source code - the only way I can see LineTo() asserting is if the HDC is NULL. That's a problem elswhere in the creation of your dc. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
-
I looked at the MFC source code - the only way I can see LineTo() asserting is if the HDC is NULL. That's a problem elswhere in the creation of your dc. Mark
Mark Salsbery Microsoft MVP - Visual C++ :java:
hi , Thats great as what you said. The problem was in creating the dc. The code was
void CThreadDemoView::OnMenuOffline()
{
// TODO: Add your command handler code here
CClientDC dc(this);
CreateThreadsToPlot(pDC, CPoint(100,100) );
}CreateThreadsToPlot will create the required no of threads to plot the points. After seeing your reply i tried this as a last attempt before giving it up. I went and browsed into the gdi code and found that my dc was not null. but surprisingly i think its invalid. This could be probably one of the reason i might have got the assertion. The code change was
void CThreadDemoView::OnMenuOffline()
{
// TODO: Add your command handler code here
CDC* pDC =GetDC();//code changed here only
CreateThreadsToPlot((CDC*)pDC, CPoint(100,100) );
}This way of getting the DC has fixed the same issue without changing not even a single line of code in the program. Thank you very much Mr. Mark Salsbery. By, Manu