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
CODE PROJECT For Those Who Code
  • Home
  • Articles
  • FAQ
Community
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. How to delete handles of a thread created with AfxBeginThread

How to delete handles of a thread created with AfxBeginThread

Scheduled Pinned Locked Moved C / C++ / MFC
c++questionperformancetutorial
9 Posts 2 Posters 1 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
    keret
    wrote on last edited by
    #1

    I have an MFC dialog application. It monitors certain types of windows and collects information on them. I start a new thread for every window based on it's title. I use a timer to find windows that meet the criteria. I created a struct named ThreadInfo and I pass it to the thread. At the end I either close the monitored window(s) or close my dialogs. This causes several memory leaks. Here is the code in the timer if it finds a window that meets the criteria:

    //Create ThreadInfo
    ThreadInfo *pInfo = new ThreadInfo;

    //put the information into pInfo
    pInfo->hMainWnd = dlg->GetSafeHwnd();
    pInfo->hMonitoredWnd = hwnd;
    pInfo->x = y; //And so on...
    
    //Start thread
    CWinThread \*pThread = AfxBeginThread(ThreadFunction, (PVOID) pInfo, THREAD\_PRIORITY\_NORMAL, 0, 0);
    

    Here is the code for ThreadFunction:

    UINT ThreadFunction(LPVOID pParam)
    {
    ThreadInfo *pInfo = reinterpret_cast (pParam);

    while (IsWindow(pInfo->hMonitoredWindow))
    {
      
       do.Something;
       Sleep(100);
       
    }
    //delete pInfo;
    return 0;
    

    }

    I tried the following scenarions to eliminate or at least identify the memory leaks. The resulting leaks are below them: A: - I create pInfo and close the dialog first: thrcore.cpp 68B client block mydlg.cpp 748B normal block strcore.cpp 46B normal block B: - I create pInfo and close the monitored window first: mydlg.cpp 748B nromal block strcore.cpp 46B normal block C: - I create pInfo, but don't start the thread: mydlg.cpp 748B normal block strcore.cpp 46B normal block D: - I don't create pInfo and pass NULL to the thread: no leaks! E: - I delete pInfo in ThreadFunction and close monitored window first: no cpp file, 160B normal block F: - I delete pInfo in ThreadFunction and close dialog first: no cpp file, 160B normal block thrcore.cpp 68B client block mydlg.cpp 748B normal block strcore.cpp 46B normal block So I think the 748B and 46B blocks are for pInfo, while the 68B and 160B block are for pThread. But how and where should I delete them? I think I should delete them in the dialog, but how do I send a message from the thread when it ends? And how I delete the handles if I close the dialog first?

    S 1 Reply Last reply
    0
    • K keret

      I have an MFC dialog application. It monitors certain types of windows and collects information on them. I start a new thread for every window based on it's title. I use a timer to find windows that meet the criteria. I created a struct named ThreadInfo and I pass it to the thread. At the end I either close the monitored window(s) or close my dialogs. This causes several memory leaks. Here is the code in the timer if it finds a window that meets the criteria:

      //Create ThreadInfo
      ThreadInfo *pInfo = new ThreadInfo;

      //put the information into pInfo
      pInfo->hMainWnd = dlg->GetSafeHwnd();
      pInfo->hMonitoredWnd = hwnd;
      pInfo->x = y; //And so on...
      
      //Start thread
      CWinThread \*pThread = AfxBeginThread(ThreadFunction, (PVOID) pInfo, THREAD\_PRIORITY\_NORMAL, 0, 0);
      

      Here is the code for ThreadFunction:

      UINT ThreadFunction(LPVOID pParam)
      {
      ThreadInfo *pInfo = reinterpret_cast (pParam);

      while (IsWindow(pInfo->hMonitoredWindow))
      {
        
         do.Something;
         Sleep(100);
         
      }
      //delete pInfo;
      return 0;
      

      }

      I tried the following scenarions to eliminate or at least identify the memory leaks. The resulting leaks are below them: A: - I create pInfo and close the dialog first: thrcore.cpp 68B client block mydlg.cpp 748B normal block strcore.cpp 46B normal block B: - I create pInfo and close the monitored window first: mydlg.cpp 748B nromal block strcore.cpp 46B normal block C: - I create pInfo, but don't start the thread: mydlg.cpp 748B normal block strcore.cpp 46B normal block D: - I don't create pInfo and pass NULL to the thread: no leaks! E: - I delete pInfo in ThreadFunction and close monitored window first: no cpp file, 160B normal block F: - I delete pInfo in ThreadFunction and close dialog first: no cpp file, 160B normal block thrcore.cpp 68B client block mydlg.cpp 748B normal block strcore.cpp 46B normal block So I think the 748B and 46B blocks are for pInfo, while the 68B and 160B block are for pThread. But how and where should I delete them? I think I should delete them in the dialog, but how do I send a message from the thread when it ends? And how I delete the handles if I close the dialog first?

      S Offline
      S Offline
      Stuart Dootson
      wrote on last edited by
      #2

      1. Why not take a local copy of *pInfo early in the thread function, so you can delete pInfo early:

      UINT ThreadFunction(LPVOID pParam)
      {
      ThreadInfo info(reinterpret_cast<ThreadInfo*>(pParam));
      delete reinterpret_cast<ThreadInfo*>(pParam);

      while (IsWindow(info.hMonitoredWindow))
      {
        
         do.Something;
         Sleep(100);
         
      }
      return 0;
      

      }

      2. Do you keep track of all the threads you've created? Doesn't look like it. Store them in a vector or something and delete them in your dialog's WM_CLOSE handler. 3. If the monitored windows aren't closed, does the thread terminate? You probably ought to have some way of telling the threads to exit even if their monitored window still exists. Basically, you need to think about the likely lifetimes of objects and work out where you need to be deleting objects.

      Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

      K 1 Reply Last reply
      0
      • S Stuart Dootson

        1. Why not take a local copy of *pInfo early in the thread function, so you can delete pInfo early:

        UINT ThreadFunction(LPVOID pParam)
        {
        ThreadInfo info(reinterpret_cast<ThreadInfo*>(pParam));
        delete reinterpret_cast<ThreadInfo*>(pParam);

        while (IsWindow(info.hMonitoredWindow))
        {
          
           do.Something;
           Sleep(100);
           
        }
        return 0;
        

        }

        2. Do you keep track of all the threads you've created? Doesn't look like it. Store them in a vector or something and delete them in your dialog's WM_CLOSE handler. 3. If the monitored windows aren't closed, does the thread terminate? You probably ought to have some way of telling the threads to exit even if their monitored window still exists. Basically, you need to think about the likely lifetimes of objects and work out where you need to be deleting objects.

        Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

        K Offline
        K Offline
        keret
        wrote on last edited by
        #3

        Thanks! 1. This didn't compile, error was: error C2664: 'ThreadInfo::ThreadInfo(const ThreadInfo &)' : cannot convert parameter 1 from 'ThreadInfo *' to 'const ThreadInfo &' but I used the following:

        ThreadInfo *pInfo = reinterpret_cast (pParam);
        ThreadInfo info = *pInfo;
        delete pInfo;

        And it seems to work. The 748B and 160B blocks are eliminated. 2. I had a threads vector earlier, but I didn't use it. Now I use it as you recommended, but I use ON_WM_DESTROY (I switched off the close button):

        void CFredoDlg::OnDestroy()
        {
        //delete threads;
        for(vector::size_type i = 0; i < threads.size(); i++)
        {
        threads.erase(threads.begin() + i);
        }

        }

        But the 68B and 46B blocks are still there. Now I will try to find a way to terminate the threads. If you have a solution for that, don't keep it!

        S 1 Reply Last reply
        0
        • K keret

          Thanks! 1. This didn't compile, error was: error C2664: 'ThreadInfo::ThreadInfo(const ThreadInfo &)' : cannot convert parameter 1 from 'ThreadInfo *' to 'const ThreadInfo &' but I used the following:

          ThreadInfo *pInfo = reinterpret_cast (pParam);
          ThreadInfo info = *pInfo;
          delete pInfo;

          And it seems to work. The 748B and 160B blocks are eliminated. 2. I had a threads vector earlier, but I didn't use it. Now I use it as you recommended, but I use ON_WM_DESTROY (I switched off the close button):

          void CFredoDlg::OnDestroy()
          {
          //delete threads;
          for(vector::size_type i = 0; i < threads.size(); i++)
          {
          threads.erase(threads.begin() + i);
          }

          }

          But the 68B and 46B blocks are still there. Now I will try to find a way to terminate the threads. If you have a solution for that, don't keep it!

          S Offline
          S Offline
          Stuart Dootson
          wrote on last edited by
          #4

          keret wrote:

          But the 68B and 46B blocks are still there

          Implies you have a thread object and a string that you haven't deleted.

          keret wrote:

          Now I will try to find a way to terminate the threads. If you have a solution for that, don't keep it!

          You could use a global boolean-ish variable. You would set it using InterlockedExchange[^] and read as you would any other variable. Set it to zero before any threads are started and to one when you want to exit. Use this code to set it (let's presume it's called letsExitNow)

          InterlockedExchange(&letsExitNow, 1);

          Now, in each thread, you would change your with loop to somethig like this:

          while (!letsExitNow && IsWindow(pInfo->hMonitoredWindow))
          

          In the ON_WM_DESTROY handler, wait for each thread handle to be signalled (signalled means the thread has exited) - you can use WaitForSingleObject[^] or WaitForMultipleObjects[^] to do that.

          Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

          K 1 Reply Last reply
          0
          • S Stuart Dootson

            keret wrote:

            But the 68B and 46B blocks are still there

            Implies you have a thread object and a string that you haven't deleted.

            keret wrote:

            Now I will try to find a way to terminate the threads. If you have a solution for that, don't keep it!

            You could use a global boolean-ish variable. You would set it using InterlockedExchange[^] and read as you would any other variable. Set it to zero before any threads are started and to one when you want to exit. Use this code to set it (let's presume it's called letsExitNow)

            InterlockedExchange(&letsExitNow, 1);

            Now, in each thread, you would change your with loop to somethig like this:

            while (!letsExitNow && IsWindow(pInfo->hMonitoredWindow))
            

            In the ON_WM_DESTROY handler, wait for each thread handle to be signalled (signalled means the thread has exited) - you can use WaitForSingleObject[^] or WaitForMultipleObjects[^] to do that.

            Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

            K Offline
            K Offline
            keret
            wrote on last edited by
            #5

            My TreadFunction is in a separate file (MyThread.cpp). How can I reference letsExitNow from there? Or should I put the code in MyDlg.cpp?

            S 1 Reply Last reply
            0
            • K keret

              My TreadFunction is in a separate file (MyThread.cpp). How can I reference letsExitNow from there? Or should I put the code in MyDlg.cpp?

              S Offline
              S Offline
              Stuart Dootson
              wrote on last edited by
              #6

              Add a definition for letsExitNow in one file:

              LONG letsExitNow;

              and an external declaration in the other:

              extern LONG letsExitNow;

              Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

              K 1 Reply Last reply
              0
              • S Stuart Dootson

                Add a definition for letsExitNow in one file:

                LONG letsExitNow;

                and an external declaration in the other:

                extern LONG letsExitNow;

                Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                K Offline
                K Offline
                keret
                wrote on last edited by
                #7

                Sorry, I have never used extern before. I put this in MyDlg.h:

                public:
                LONG letsExitNow

                I put this in CMyDlg::OnInitDialog:

                InterlockedExchange(&letsExitNow, 0);

                And I put this in ThreadFunction:

                extern LONG letsExitNow;

                But I got an "unresolved external symbol "long letsExitNow"" error. Did I something wrong?

                S 1 Reply Last reply
                0
                • K keret

                  Sorry, I have never used extern before. I put this in MyDlg.h:

                  public:
                  LONG letsExitNow

                  I put this in CMyDlg::OnInitDialog:

                  InterlockedExchange(&letsExitNow, 0);

                  And I put this in ThreadFunction:

                  extern LONG letsExitNow;

                  But I got an "unresolved external symbol "long letsExitNow"" error. Did I something wrong?

                  S Offline
                  S Offline
                  Stuart Dootson
                  wrote on last edited by
                  #8

                  Minor mis-understanding :-) Put the LONG letsExitNow in MyDlg.cpp - NOT in a method, just in the file.

                  Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

                  K 1 Reply Last reply
                  0
                  • S Stuart Dootson

                    Minor mis-understanding :-) Put the LONG letsExitNow in MyDlg.cpp - NOT in a method, just in the file.

                    Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p

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

                    Thank You, I really appreciate your help. This was a complicated problem (for me now at least). The 160B object was another struct I didn't include in the code above.

                    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