locked
References to Controls being held by HelpProvider RRS feed

  • Question

  • Is there a way to get a HelpProvider to release a reference to a Control it has been passed in a call to SetShowHelp or SetHelpKeyword?  ResetShowHelp and SetShowHelp(Control, false) do not do the trick.

    Our application has a singleton HelpProvider.   Forms access this singleton in their Form_Load, but this appears to cause an unavoidable object leak (our application creates and destroys forms over and over).
    Tuesday, August 7, 2007 12:26 AM

Answers

  • Hmm, "unsupported use of a component" jumps to mind.
    Tuesday, August 7, 2007 5:42 AM

All replies

  • Using a singleton HelpProvider is not a good idea, make it a component of the form so it gets disposed together with the form.  Nevertheless, ResetShowHelp() removes the control from the internal Hashtable it keeps.  With a singleton, you'd have to iterate the Controls collection of the form and any container controls in the FormClosing event:

        private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
          releaseHelp(this.Controls);
        }
        private void releaseHelp(Control.ControlCollection ctls) {
          foreach (Control ctl in ctls) {
            helpProvider1.ResetShowHelp(ctl);
            releaseHelp(ctl.Controls);
          }
        }

    Where helpProvider1 would be your HelpProvider instance.
    Tuesday, August 7, 2007 12:51 AM
  • Thanks again, Hans.  I think we'll have to go with making the HelpProvider a component of the form.

    However, if ResetShowHelp() is supposed to release the reference, then there appears to be a bug in it.  I can't find any way to get a HelpProvider to release a reference to a Form. 

    On my system, in this application it takes about 3 or 4 iterations of creating and closing Form2 before I get an out of memory error.  Can anybody rewrite Form1.form2_FormClosed() such that the reference is released?

        public partial class Form1 : Form
        {
            private HelpProvider m_HelpProvider = new HelpProvider();
            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                GC.Collect();
                GC.WaitForPendingFinalizers();

                Form2 form2 = new Form2();
                m_HelpProvider.SetHelpNavigator(form2, HelpNavigator.Index);
                form2.FormClosed += new FormClosedEventHandler(form2_FormClosed);
                form2.Show();
            }

            void form2_FormClosed(object sender, FormClosedEventArgs e)
            {
                m_HelpProvider.ResetShowHelp((Control)sender);
                // this doesn't work either:
                // m_HelpProvider.SetShowHelp((Control)sender, false);
            }
        }

        public partial class Form2 : Form
        {
            private int[] x = new int[59999999];
            public Form2()
            {
                InitializeComponent();
            }
        }






    Tuesday, August 7, 2007 3:44 AM
  • The SetHelpNavigator() method call is the killer.  That adds a reference to the form to another hash table that can't be cleared.
    Tuesday, August 7, 2007 4:33 AM
  • The same goes for all the Set methods on HelpProvider.  The object is impossible to use in such a way that it doesn't permanently grab references.  This seems like a bug.
    Tuesday, August 7, 2007 4:46 AM
  • Hmm, "unsupported use of a component" jumps to mind.
    Tuesday, August 7, 2007 5:42 AM