none
Problem with removing Controls from memory RRS feed

  • Question

  • Hi!

    At first my app creates TabControl and some controls on it at run-time. Like this

    void CreateGUI(int S, System::Windows::Forms::Form^ Form1)  
    {  
        TabControl^ MyTab = gcnew TabControl;  
        array <TabPage^>MyPages = gcnew array <TabPage^> (2);  
        array< TextBox>VarMin = gcnew array<TextBox^>(5);  
          
        Form1->SuspendLayout();  
        for (i=0;i<MyPages->Length;i++)    
        {  
            MyPages[i] = gcnew TabPage;  
            MyPages[i]->SuspendLayout();  
            MyPages[i]->Text=Convert::ToString(i);  
        }  
        MyTab->Controls->AddRange(MyPages);  
        MyTab->Location = Point(12,30);  
        MyTab->SelectedIndex = 0;  
        MyTab->Size = Size(640, 480);  
        MyTab->Name=L"MyTab1";  
     
        for (int j=0;j<5;j++)    
        {  
            VarMin[j] = gcnew TextBox;  
            VarMin[j]->Location = System::Drawing::Point(155, 15+j*40);  
            VarMin[j]->Size = System::Drawing::Size(40, 20);  
            VarMin[j]->Text = Convert::ToString(j+S);  
            VarMin[j]->Name=L"VarMin_"+Convert::ToString(j);  
            MyPages[0]->Controls->Add(VarMin[j]);     
        }  
        Form1->Controls->Add(MyTab);  
        Form1->ResumeLayout();  


    Then I refresh it like this:

    void RefreshGUI (System::Windows::Forms::Form^ Form1)  
    {  
        IEnumerator^ myTabEnum = Form1->Controls->GetEnumerator();  
        while ( myTabEnum->MoveNext() )  
        {  
            Control^ tempTabCtrl = safe_cast<Control^>(myTabEnum->Current);  
            if ( tempTabCtrl->Name->Equals( "MyTab1" ) )  
                {  
                IEnumerator^ myPageEnum = tempTabCtrl->Controls->GetEnumerator();  
                while (myPageEnum->MoveNext())  
                {  
                    Control^ tempPageCtrl = safe_cast<Control^>(myPageEnum->Current);  
                    IEnumerator^ myEnum = tempPageCtrl->Controls->GetEnumerator();  
                    while (myEnum->MoveNext())  
                    {  
                        Control^ tempCtrl = safe_cast<Control^>(myEnum->Current);  
                        tempPageCtrl->Controls->Clear();  
                    }  
                }  
                tempTabCtrl->Controls->Clear();  
            }  
        }  
        CreateGUI(55,Form1);  


    or like this

    void RefreshGUI (System::Windows::Forms::Form^ Form1)  
    {  
    Formmm->Controls->RemoveByKey("MyTab1");  
    CreateGUI(55,Form1);  

    But with each call of RefreshGUI memory occupied by program does not decrease, when I call CreateGUI once more it increases and at least I have an error:

    An unhandled exception of type 'System.ComponentModel.Win32Exception' occurred in System.Windows.Forms.dll
    dditional information: Error creating window handle.

    What is the reason of such error?




    • Edited by m.Quantum Monday, June 23, 2008 1:19 PM Bad subject
    Monday, June 23, 2008 1:13 PM

Answers

  • C++/CLI syntax fluke.  It's managed class destructor is in reality a call to Dispose().  Making Dispose() completely unavailable was a bit unnecessary.
    Hans Passant.
    • Marked as answer by m.Quantum Tuesday, June 24, 2008 11:46 AM
    • Unmarked as answer by m.Quantum Tuesday, June 24, 2008 11:46 AM
    • Marked as answer by m.Quantum Tuesday, June 24, 2008 11:46 AM
    Tuesday, June 24, 2008 10:04 AM
    Moderator

All replies

  • You must call Dispose() on every control you remove.  Rather a flaw in RemoveByKey() and Clear() but the MSDN library docs warn about this.  Without it, you'll eventually run out of window handles if the garbage collector doesn't get a chance to run.
    Hans Passant.
    Monday, June 23, 2008 6:39 PM
    Moderator
  • How do you warn a user of such a condition if its source is outside your application?

    This exception can also occur if the user is running too many other applications and the OS itself has run out of Windows Handles. I've been looking for a way to warn the user of such low memory conditions, but in trying to use MessageBox.Show, I run into an obvious problem -- there aren't any windows to show even a simple message box.

    Is there a solution to this? I notice Outlook is able to show a low memory warning message box, so perhaps it's a question of using a lower level API.
    Tuesday, June 24, 2008 4:15 AM
  • Nah, you're fixing the wrong problem.  Windows running a bunch of apps should never even be close to running out of handles.  If it happens, you've got a program that is leaking handles.  It is easy enough to find, Task manager can show the handle count.  The best fix for such a program is to uninstall it if you can't get the vendor to repair the problem.
    Hans Passant.
    Tuesday, June 24, 2008 4:29 AM
    Moderator
  • When I'm trying to call Dispose() on control like this

    void RefreshGUI (System::Windows::Forms::Form^ Form1)  
    {  
       IEnumerator^ myTabEnum = Form1->Controls->GetEnumerator();  
       while ( myTabEnum->MoveNext() )  
       {  
            Control^ tempTabCtrl = safe_cast<Control^>(myTabEnum->Current);  
            tempTabCtrl->Dispose();  
       }  
       CreateGUI(55,Form1);  


    compiler says (Of course i do use System::Windows::Forms namespace.):

    error C2039: 'Dispose' : is not a member of 'System::Windows::Forms::Control'
    1> c:\windows\microsoft.net\framework\v2.0.50727\system.windows.forms.dll : see declaration of 'System::Windows::Forms::Control'
    1> You should invoke the destructor, '~Control' instead

    When I use ~Contrlol() evreything seems to bo ok, but what's wrong with Dispose?



    • Edited by m.Quantum Tuesday, June 24, 2008 7:53 AM some additional information
    Tuesday, June 24, 2008 7:32 AM
  • C++/CLI syntax fluke.  It's managed class destructor is in reality a call to Dispose().  Making Dispose() completely unavailable was a bit unnecessary.
    Hans Passant.
    • Marked as answer by m.Quantum Tuesday, June 24, 2008 11:46 AM
    • Unmarked as answer by m.Quantum Tuesday, June 24, 2008 11:46 AM
    • Marked as answer by m.Quantum Tuesday, June 24, 2008 11:46 AM
    Tuesday, June 24, 2008 10:04 AM
    Moderator
  • > Nah, you're fixing the wrong problem.  Windows running a bunch of apps should never even be close to running out of handles

    Try running 10-20 copies of Visual Studio 2005 and you'll see what I am talking about.

    Windows will run out of handles if you run enough applications, even if none is necessarily leaking memory. It appears to be a limitation imposed by XP's support for old school 16 bit applications.

    I know the situation seems silly, but our users will do things like that and expect that when our application launches it properly handles this low memory condition.
    Tuesday, June 24, 2008 2:25 PM