Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. Multithread and GDI Issues

Multithread and GDI Issues

Scheduled Pinned Locked Moved C / C++ / MFC
graphicshelp
13 Posts 5 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kanduripavan
    wrote on last edited by
    #1

    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

    R C M 3 Replies Last reply
    0
    • K kanduripavan

      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

      R Offline
      R Offline
      rp_suman
      wrote on last edited by
      #2

      Hi, Pls try InitializeCriticalSection() or InitializeCriticalSectionAndSpinCount() before calling EnterCriticalSection() function. See the remarks section here: InitializeCriticalSectionAndSpinCount Function[^] Best Regards, Suman

      1 Reply Last reply
      0
      • K kanduripavan

        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

        C Offline
        C Offline
        Cedric Moonen
        wrote on last edited by
        #3

        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]

        K 1 Reply Last reply
        0
        • C Cedric Moonen

          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]

          K Offline
          K Offline
          kanduripavan
          wrote on last edited by
          #4

          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

          C 1 Reply Last reply
          0
          • K kanduripavan

            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

            C Offline
            C Offline
            Cedric Moonen
            wrote on last edited by
            #5

            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]

            K 2 Replies Last reply
            0
            • C Cedric Moonen

              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]

              K Offline
              K Offline
              kanduripavan
              wrote on last edited by
              #6

              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

              1 Reply Last reply
              0
              • K kanduripavan

                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

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #7

                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:

                K 1 Reply Last reply
                0
                • C Cedric Moonen

                  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]

                  K Offline
                  K Offline
                  kanduripavan
                  wrote on last edited by
                  #8

                  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.

                  R 1 Reply Last reply
                  0
                  • M Mark Salsbery

                    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:

                    K Offline
                    K Offline
                    kanduripavan
                    wrote on last edited by
                    #9

                    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.

                    M 2 Replies Last reply
                    0
                    • K kanduripavan

                      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.

                      R Offline
                      R Offline
                      Rajkumar R
                      wrote on last edited by
                      #10

                      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.

                      1 Reply Last reply
                      0
                      • K kanduripavan

                        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.

                        M Offline
                        M Offline
                        Mark Salsbery
                        wrote on last edited by
                        #11

                        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:

                        1 Reply Last reply
                        0
                        • K kanduripavan

                          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.

                          M Offline
                          M Offline
                          Mark Salsbery
                          wrote on last edited by
                          #12

                          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:

                          K 1 Reply Last reply
                          0
                          • M Mark Salsbery

                            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:

                            K Offline
                            K Offline
                            kanduripavan
                            wrote on last edited by
                            #13

                            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

                            1 Reply Last reply
                            0
                            Reply
                            • Reply as topic
                            Log in to reply
                            • Oldest to Newest
                            • Newest to Oldest
                            • Most Votes


                            • Login

                            • Don't have an account? Register

                            • Login or register to search.
                            • First post
                              Last post
                            0
                            • Categories
                            • Recent
                            • Tags
                            • Popular
                            • World
                            • Users
                            • Groups