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. How to end a thread

How to end a thread

Scheduled Pinned Locked Moved C / C++ / MFC
tutorialquestion
16 Posts 4 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.
  • C Offline
    C Offline
    Chen XuNuo
    wrote on last edited by
    #1

    I am doing a TankGame program,and I write a CBullet class.I write a thread function to make it move when it is created: UINT BulletGo(LPVOID pParam) { CBullet* bullet=(CBullet*)pParam; while(TRUE) { switch(bullet->m_bCanGo.GetDirection()) { case UP: bullet->GoUp(); break; case DOWN: bullet->GoDown(); break; case LEFT: bullet->GoLeft(); break; case RIGHT: bullet->GoRight(); break; } if(!bullet->m_bCanGo) break; else bullet->MoveWindow(bullet->GetPosition().x, bullet->GetPosition().y, bullet->GetThisRect().Height(), bullet->GetThisRec().Width()); Sleep(30); } return 0; } int CBullet::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CStatic::OnCreate(lpCreateStruct) == -1) return -1; m_bCanGo=TRUE; m_pThread=AfxBeginThread(BulletGo,this); //begin thread return 0; } BOOL CBullet::GoDown() { if((m_ptPosition.y+m_rtThis.Height())>m_rtParent.bottom) { m_ptPosition.y+=2; m_bCanGo=TRUE; return TRUE; } else { this->DestroyWindow(); m_bCreated=FALSE; m_bCanGo=FALSE; return FALSE; } } When the bullet go down and hit the bottom of client rect the program apprear errors.Why...Don't the "break" in the BulletGo() end the thread?

    L M C 3 Replies Last reply
    0
    • C Chen XuNuo

      I am doing a TankGame program,and I write a CBullet class.I write a thread function to make it move when it is created: UINT BulletGo(LPVOID pParam) { CBullet* bullet=(CBullet*)pParam; while(TRUE) { switch(bullet->m_bCanGo.GetDirection()) { case UP: bullet->GoUp(); break; case DOWN: bullet->GoDown(); break; case LEFT: bullet->GoLeft(); break; case RIGHT: bullet->GoRight(); break; } if(!bullet->m_bCanGo) break; else bullet->MoveWindow(bullet->GetPosition().x, bullet->GetPosition().y, bullet->GetThisRect().Height(), bullet->GetThisRec().Width()); Sleep(30); } return 0; } int CBullet::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CStatic::OnCreate(lpCreateStruct) == -1) return -1; m_bCanGo=TRUE; m_pThread=AfxBeginThread(BulletGo,this); //begin thread return 0; } BOOL CBullet::GoDown() { if((m_ptPosition.y+m_rtThis.Height())>m_rtParent.bottom) { m_ptPosition.y+=2; m_bCanGo=TRUE; return TRUE; } else { this->DestroyWindow(); m_bCreated=FALSE; m_bCanGo=FALSE; return FALSE; } } When the bullet go down and hit the bottom of client rect the program apprear errors.Why...Don't the "break" in the BulletGo() end the thread?

      L Offline
      L Offline
      Llasus
      wrote on last edited by
      #2

      what exactly is the error?

      C 1 Reply Last reply
      0
      • C Chen XuNuo

        I am doing a TankGame program,and I write a CBullet class.I write a thread function to make it move when it is created: UINT BulletGo(LPVOID pParam) { CBullet* bullet=(CBullet*)pParam; while(TRUE) { switch(bullet->m_bCanGo.GetDirection()) { case UP: bullet->GoUp(); break; case DOWN: bullet->GoDown(); break; case LEFT: bullet->GoLeft(); break; case RIGHT: bullet->GoRight(); break; } if(!bullet->m_bCanGo) break; else bullet->MoveWindow(bullet->GetPosition().x, bullet->GetPosition().y, bullet->GetThisRect().Height(), bullet->GetThisRec().Width()); Sleep(30); } return 0; } int CBullet::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CStatic::OnCreate(lpCreateStruct) == -1) return -1; m_bCanGo=TRUE; m_pThread=AfxBeginThread(BulletGo,this); //begin thread return 0; } BOOL CBullet::GoDown() { if((m_ptPosition.y+m_rtThis.Height())>m_rtParent.bottom) { m_ptPosition.y+=2; m_bCanGo=TRUE; return TRUE; } else { this->DestroyWindow(); m_bCreated=FALSE; m_bCanGo=FALSE; return FALSE; } } When the bullet go down and hit the bottom of client rect the program apprear errors.Why...Don't the "break" in the BulletGo() end the thread?

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

        You need to synchronize the shutdown a bit better. By the time you set m_bCanGo=FALSE you've destroyed the window, yet your thread is still doing (attempting) operations on it. Try something like this:

        BOOL CBullet::GoDown()
        {
        if((m_ptPosition.y+m_rtThis.Height())>m_rtParent.bottom)
        {
        m_ptPosition.y+=2;
        m_bCanGo=TRUE;
        return TRUE;
        }
        else
        {
        m_bCanGo=FALSE; ::WaitForSingleObject(m_pThread, INFINITE);
        this->DestroyWindow();
        m_bCreated=FALSE;
        return FALSE;
        }
        }

        Mark Salsbery Microsoft MVP - Visual C++ :java:

        C 1 Reply Last reply
        0
        • C Chen XuNuo

          I am doing a TankGame program,and I write a CBullet class.I write a thread function to make it move when it is created: UINT BulletGo(LPVOID pParam) { CBullet* bullet=(CBullet*)pParam; while(TRUE) { switch(bullet->m_bCanGo.GetDirection()) { case UP: bullet->GoUp(); break; case DOWN: bullet->GoDown(); break; case LEFT: bullet->GoLeft(); break; case RIGHT: bullet->GoRight(); break; } if(!bullet->m_bCanGo) break; else bullet->MoveWindow(bullet->GetPosition().x, bullet->GetPosition().y, bullet->GetThisRect().Height(), bullet->GetThisRec().Width()); Sleep(30); } return 0; } int CBullet::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CStatic::OnCreate(lpCreateStruct) == -1) return -1; m_bCanGo=TRUE; m_pThread=AfxBeginThread(BulletGo,this); //begin thread return 0; } BOOL CBullet::GoDown() { if((m_ptPosition.y+m_rtThis.Height())>m_rtParent.bottom) { m_ptPosition.y+=2; m_bCanGo=TRUE; return TRUE; } else { this->DestroyWindow(); m_bCreated=FALSE; m_bCanGo=FALSE; return FALSE; } } When the bullet go down and hit the bottom of client rect the program apprear errors.Why...Don't the "break" in the BulletGo() end the thread?

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

          If you want my advice, I don't think that you need to create a thread for that. If you keep that logic, it would mean that you will create a thread for every bullet in your game. And probably for every ennemy too. Honnestly, I don't think this is a good idea. You should better process the position of all your 'entities' (bullets, ennemies, ...) in the message pump and then draw everything on the screen. You don't need a thread for that. I don't know if you are using the MFC's or not, but if that's the case, then you won't have access to the message pump. But you could override the OnIdle function from your App class and do it there.

          Cédric Moonen Software developer
          Charting control [v1.2]

          M C 2 Replies Last reply
          0
          • C Cedric Moonen

            If you want my advice, I don't think that you need to create a thread for that. If you keep that logic, it would mean that you will create a thread for every bullet in your game. And probably for every ennemy too. Honnestly, I don't think this is a good idea. You should better process the position of all your 'entities' (bullets, ennemies, ...) in the message pump and then draw everything on the screen. You don't need a thread for that. I don't know if you are using the MFC's or not, but if that's the case, then you won't have access to the message pump. But you could override the OnIdle function from your App class and do it there.

            Cédric Moonen Software developer
            Charting control [v1.2]

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

            OnIdle...bleh. I'd prefer a multimedia timer for smoother frame rate :) Cheers :beer:

            Mark Salsbery Microsoft MVP - Visual C++ :java:

            1 Reply Last reply
            0
            • L Llasus

              what exactly is the error?

              C Offline
              C Offline
              Chen XuNuo
              wrote on last edited by
              #6

              The application pops up a dialog about error saying that Debug Assertion Failed! Program : D:\Code\TankGame\Debug\TankGame.exe File : wincore.cpp Line : 304 ......

              1 Reply Last reply
              0
              • M Mark Salsbery

                You need to synchronize the shutdown a bit better. By the time you set m_bCanGo=FALSE you've destroyed the window, yet your thread is still doing (attempting) operations on it. Try something like this:

                BOOL CBullet::GoDown()
                {
                if((m_ptPosition.y+m_rtThis.Height())>m_rtParent.bottom)
                {
                m_ptPosition.y+=2;
                m_bCanGo=TRUE;
                return TRUE;
                }
                else
                {
                m_bCanGo=FALSE; ::WaitForSingleObject(m_pThread, INFINITE);
                this->DestroyWindow();
                m_bCreated=FALSE;
                return FALSE;
                }
                }

                Mark Salsbery Microsoft MVP - Visual C++ :java:

                C Offline
                C Offline
                Chen XuNuo
                wrote on last edited by
                #7

                Thank you for you advice.But it helps nothing to the problem... :sigh:

                M 1 Reply Last reply
                0
                • C Cedric Moonen

                  If you want my advice, I don't think that you need to create a thread for that. If you keep that logic, it would mean that you will create a thread for every bullet in your game. And probably for every ennemy too. Honnestly, I don't think this is a good idea. You should better process the position of all your 'entities' (bullets, ennemies, ...) in the message pump and then draw everything on the screen. You don't need a thread for that. I don't know if you are using the MFC's or not, but if that's the case, then you won't have access to the message pump. But you could override the OnIdle function from your App class and do it there.

                  Cédric Moonen Software developer
                  Charting control [v1.2]

                  C Offline
                  C Offline
                  Chen XuNuo
                  wrote on last edited by
                  #8

                  Mmmm...I think if I draw the 'entities' with DC,I think the application would take large CPU resource,so I do it in thread.And I think using thread to control the enemies and the bullets easier. I will try you advice, thank you~

                  1 Reply Last reply
                  0
                  • C Chen XuNuo

                    Thank you for you advice.But it helps nothing to the problem... :sigh:

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

                    If that's the case, then you need to debug. Can you post more specifics on the problem? Does it crash? If so, on what line? If not, does the thread ever exit? If not, why? Use breakpoints and single step to find out. Etc... Running in the debugger you should be able to find what line of code is causing problems and trace back to why there's a problem. Your original code is not going to work correctly. You MUST manage synchronization of your threads! Also, using a separate thread doesn't mean less CPU cycles are used, as implied by your post below. One thread per moving object will start to degrade performance once you have many objects going at once. Plus it's wasteful of resources. Even one thread on a modern PC is capable of tracking and rendering MANY moving objects.

                    Mark Salsbery Microsoft MVP - Visual C++ :java:

                    C 3 Replies Last reply
                    0
                    • M Mark Salsbery

                      If that's the case, then you need to debug. Can you post more specifics on the problem? Does it crash? If so, on what line? If not, does the thread ever exit? If not, why? Use breakpoints and single step to find out. Etc... Running in the debugger you should be able to find what line of code is causing problems and trace back to why there's a problem. Your original code is not going to work correctly. You MUST manage synchronization of your threads! Also, using a separate thread doesn't mean less CPU cycles are used, as implied by your post below. One thread per moving object will start to degrade performance once you have many objects going at once. Plus it's wasteful of resources. Even one thread on a modern PC is capable of tracking and rendering MANY moving objects.

                      Mark Salsbery Microsoft MVP - Visual C++ :java:

                      C Offline
                      C Offline
                      Chen XuNuo
                      wrote on last edited by
                      #10

                      I set a breakpoint on "return 0" in the thread function.When the bullet hit the bottom of client rect,the appliction jump to the breakpoint,and I step over,the debugger doesn't pop up error dialog until execute to the line AfxEndThread(nResult) in function UINT APIENTRY _AfxThreadEntry(void* pParam). How do you think the two methods of conrol the enemies and bullets that one use threads and the other use timer in class?Which waste more CPU resource?

                      M 1 Reply Last reply
                      0
                      • M Mark Salsbery

                        If that's the case, then you need to debug. Can you post more specifics on the problem? Does it crash? If so, on what line? If not, does the thread ever exit? If not, why? Use breakpoints and single step to find out. Etc... Running in the debugger you should be able to find what line of code is causing problems and trace back to why there's a problem. Your original code is not going to work correctly. You MUST manage synchronization of your threads! Also, using a separate thread doesn't mean less CPU cycles are used, as implied by your post below. One thread per moving object will start to degrade performance once you have many objects going at once. Plus it's wasteful of resources. Even one thread on a modern PC is capable of tracking and rendering MANY moving objects.

                        Mark Salsbery Microsoft MVP - Visual C++ :java:

                        C Offline
                        C Offline
                        Chen XuNuo
                        wrote on last edited by
                        #11

                        I have found the error:I can't end the thread after destorying the window,right? ;P

                        M 1 Reply Last reply
                        0
                        • M Mark Salsbery

                          If that's the case, then you need to debug. Can you post more specifics on the problem? Does it crash? If so, on what line? If not, does the thread ever exit? If not, why? Use breakpoints and single step to find out. Etc... Running in the debugger you should be able to find what line of code is causing problems and trace back to why there's a problem. Your original code is not going to work correctly. You MUST manage synchronization of your threads! Also, using a separate thread doesn't mean less CPU cycles are used, as implied by your post below. One thread per moving object will start to degrade performance once you have many objects going at once. Plus it's wasteful of resources. Even one thread on a modern PC is capable of tracking and rendering MANY moving objects.

                          Mark Salsbery Microsoft MVP - Visual C++ :java:

                          C Offline
                          C Offline
                          Chen XuNuo
                          wrote on last edited by
                          #12

                          I am going to be crazy..X| The problem still haven't been solved. UINT BulletGo(LPVOID pParam) { CBullet* bullet=(CBullet*)pParam; while(TRUE) { switch(bullet->GetDirection()) { case UP: bullet->GoUp(); break; case DOWN: bullet->GoDown(); break; case LEFT: bullet->GoLeft(); break; case RIGHT: bullet->GoRight(); break; } if(!bullet->m_bCanGo) break; else bullet->MoveWindow(bullet->GetPosition().x,bullet->GetPosition().y, bullet->GetThisRect().Height(),bullet->GetThisRect().Width()); Sleep(30); } return 0; } BOOL CBullet::GoDown() { if(m_rtParent.bottom==0) GetParent()->GetClientRect(&m_rtParent); if((m_ptPosition.y+m_rtThis.Height())<m_rtParent.bottom) { m_ptPosition.y+=6; m_bCanGo=TRUE; return TRUE; } else { m_bCreated=FALSE; m_bCanGo=FALSE; while( ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT) { Sleep(1); } delete m_pThread; this->DestroyWindow(); return FALSE; } } I destroy the window after ending the thread. Is the judgement: ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT right?If it is right,where is the problem.. :((

                          M 1 Reply Last reply
                          0
                          • C Chen XuNuo

                            I am going to be crazy..X| The problem still haven't been solved. UINT BulletGo(LPVOID pParam) { CBullet* bullet=(CBullet*)pParam; while(TRUE) { switch(bullet->GetDirection()) { case UP: bullet->GoUp(); break; case DOWN: bullet->GoDown(); break; case LEFT: bullet->GoLeft(); break; case RIGHT: bullet->GoRight(); break; } if(!bullet->m_bCanGo) break; else bullet->MoveWindow(bullet->GetPosition().x,bullet->GetPosition().y, bullet->GetThisRect().Height(),bullet->GetThisRect().Width()); Sleep(30); } return 0; } BOOL CBullet::GoDown() { if(m_rtParent.bottom==0) GetParent()->GetClientRect(&m_rtParent); if((m_ptPosition.y+m_rtThis.Height())<m_rtParent.bottom) { m_ptPosition.y+=6; m_bCanGo=TRUE; return TRUE; } else { m_bCreated=FALSE; m_bCanGo=FALSE; while( ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT) { Sleep(1); } delete m_pThread; this->DestroyWindow(); return FALSE; } } I destroy the window after ending the thread. Is the judgement: ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT right?If it is right,where is the problem.. :((

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

                            Chen-XuNuo wrote:

                            ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT

                            That should work fine, although you really don't need to loop. A simple ::WaitForSingleObject(m_pThread->m_hThread, INFINITE); should be good enough.

                            Chen-XuNuo wrote:

                            delete m_pThread;

                            This isn't good. CWinThread objects delete themselves by default. If you delete it twice, whichever delete happens last is going to crash! You probably should remove that line :) Mark

                            Mark Salsbery Microsoft MVP - Visual C++ :java:

                            C 1 Reply Last reply
                            0
                            • C Chen XuNuo

                              I have found the error:I can't end the thread after destorying the window,right? ;P

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

                              Chen-XuNuo wrote:

                              I can't end the thread after destorying the window,right?

                              Right :) Not if the thread is using the window!

                              Mark Salsbery Microsoft MVP - Visual C++ :java:

                              1 Reply Last reply
                              0
                              • C Chen XuNuo

                                I set a breakpoint on "return 0" in the thread function.When the bullet hit the bottom of client rect,the appliction jump to the breakpoint,and I step over,the debugger doesn't pop up error dialog until execute to the line AfxEndThread(nResult) in function UINT APIENTRY _AfxThreadEntry(void* pParam). How do you think the two methods of conrol the enemies and bullets that one use threads and the other use timer in class?Which waste more CPU resource?

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

                                Chen-XuNuo wrote:

                                How do you think the two methods of conrol the enemies and bullets that one use threads and the other use timer in class?Which waste more CPU resource?

                                Total CPU usage is going to be pretty close to the same with either method, up to a point. At some point, you can have so many threads that the system is spending too much time switching between them. That will degrade performance. There's nothing wrong with what you're doing, except scaleability. If you decide to be able to have hundreds of bullets being animated at the same time, you can still do that with one thread. There's no good reason to have a separate thread for each bullet. A fairly easy scenario for a simple game would have: 1) One thread that does ALL the drawing/rendering. This eliminates the problems with GDI/DirectX/etc. synchronization between threads. You can synchronize them, but that slows it down - waiting threads are doing nothing when they could be working :) This thread could be awakened by a multimedia timer event to provide a smooth animation frame rate. 2) A second thread to do all the calculations of bullet positions and movement of other objects. The information calculated by this thread would be used by the rendering thread so it knows where to draw stuff. If coded efficiently,, the render thread should be able to read the info it needs without ever waiting on this thread. Of course, there's an infinite number of ways to design this. My point is that you can do a LOT of processing with very few threads on modern PCs :) Mark

                                Mark Salsbery Microsoft MVP - Visual C++ :java:

                                1 Reply Last reply
                                0
                                • M Mark Salsbery

                                  Chen-XuNuo wrote:

                                  ::WaitForSingleObject(m_pThread->m_hThread,1) == WAIT_TIMEOUT

                                  That should work fine, although you really don't need to loop. A simple ::WaitForSingleObject(m_pThread->m_hThread, INFINITE); should be good enough.

                                  Chen-XuNuo wrote:

                                  delete m_pThread;

                                  This isn't good. CWinThread objects delete themselves by default. If you delete it twice, whichever delete happens last is going to crash! You probably should remove that line :) Mark

                                  Mark Salsbery Microsoft MVP - Visual C++ :java:

                                  C Offline
                                  C Offline
                                  Chen XuNuo
                                  wrote on last edited by
                                  #16

                                  Thank you very much.The problem has been solved. :rose: :)

                                  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