Question

I have this code, that runs every time a "primary menu" item is clicked. It basically fills out a submenu stackpanel with "buttoned" user controls.

    private void LoadSubMenuControls(int _menuid)
    {
        double _itemcount = 0;
        double _buttonHeight = 61;
        //fill out user permissions
        //get information  from users
        //release events and bindintgs
        foreach (Object _child in Midmenu.Children)
        {
            ((MenuButton)_child).MidMousePressed -= new MenuButton.MidMenuMouseButtonPressed(MenuButton_MidMousePressed);
            ((MenuButton)_child).DataContext = null;
        }
        Midmenu.Children.Clear();
        midScroll1.ScrollToTop();
        Midmenu.Height = MidHeight;
        Midmenu.Width = this.Width / 3;
        foreach (DataRow _row in _rxworksmenues.GetMenuItems(_menuid))
        {
            _itemcount++;
            MainScreenWPFUC.MenuButtonViewModel _butview = new MenuButtonViewModel();
            _butview.ApplyViewModel(_row,_itemcount);
            _butview.MenuButton.DataContext = _butview;
            _butview.MenuButton.Height = _buttonheight;
            _butview.MenuButton.Width = Midmenu.Width;
            _butview.MenuButton.MidMousePressed += new MenuButton.MidMenuMouseButtonPressed(MenuButton_MidMousePressed);
            Midmenu.Children.Add(_butview.MenuButton);
            Midmenu.UpdateLayout();
        }
        //When there are more items than height allows display the 
        //scrolbar and hide the border
        //also squeeze the midframe to accomodate scrollbar with width of 56 px
        if (MidHeight < _rxworksmenues.CountMenuItems(_menuid) * _buttonHeight)
        {
            midScroll1.VerticalScrollBarVisibility = ScrollBarVisibility.Visible;
            Midmenu.ScrollOwner = midScroll1;
            Midmenu.Width = this.Width /3 - 56;
            ScrollViewerBorder.BorderThickness = new Thickness(1,0,0,0);
        }
        else
        {
            midScroll1.VerticalScrollBarVisibility = ScrollBarVisibility.Hidden;
            ScrollViewerBorder.BorderThickness = new Thickness(1,0,1,0);
        }


        //TFS 10560
        //Forces garbage collection to rpevent memory link occuring in this function

        //System.Threading.Thread.Sleep(200);
        //GC.Collect();
        //GC.WaitForPendingFinalizers();

    }

What I've noticed happening is that every time this code is executed the memory on the process goes up several K and never lets down. What I've discovered from reading is that forcing garbage collection can help, and it does, but I've also read it's not a good practice and want to find where the leak actually occurs.

To state a question, how can I capture the leak, and is the code the cause of it?

Thank you.

GetMenuItems comes from this class.

 public class Menues
    {
        private DataTable _table = new DataTable("menues");

        public Menues()
        {
        }

        public void Fill(int sysuserid, string dbconnection)
        {
//            DateTime start = new DateTime(DateTime.Now.Ticks);
            SqlConnection _conn = new SqlConnection( dbconnection);
            SqlCommand _comm = new SqlCommand("Get_RxWorks_Menues",_conn);
            _comm.CommandType = CommandType.StoredProcedure;
            SqlParameter _param = new SqlParameter("@sysuserid",sysuserid);
            _comm.Parameters.Add(_param);
            SqlDataAdapter _da = new SqlDataAdapter(_comm);
            _da.Fill(_table);
 //           DateTime end = new DateTime(DateTime.Now.Ticks);
 //           MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
        }
        /// <summary>
        /// Fetches main menu items when parentid is ommited
        /// or submenu items when int parentid is specified
        /// </summary>
        /// <returns></returns>
        public DataRow[] GetMenuItems()
        {

            return _table.Select("parentid=0");

        }
        /// <summary>
        /// Fetches main menu items when parentid is ommited
        /// or submenu items when int parentid is specified
        /// </summary>
        /// <returns></returns>

        public DataRow[] GetMenuItems(int parentid)
        {
            return _table.Select("parentid=" + parentid);
        }

        /// <summary>
        /// Returns number of menu items, when empty returns left menu
        /// </summary>
        /// <returns></returns>
        public int CountMenuItems()
        {
                return _table.Select("parentid=0").Length;
        }
        /// <summary>
        /// Returns number of menu items, when empty returns left menu
        /// </summary>
        /// <returns></returns>
        public int CountMenuItems(int parentid)
        {
            return _table.Select("parentid=" + parentid).Length;
        }

        public DataTable MenuTable
        {
            get
            {
                return _table;
            }
        }
Was it helpful?

Solution

In your code:

public void Fill(int sysuserid, string dbconnection)
        {
//            DateTime start = new DateTime(DateTime.Now.Ticks);
            SqlConnection _conn = new SqlConnection( dbconnection);
            SqlCommand _comm = new SqlCommand("Get_RxWorks_Menues",_conn);
            _comm.CommandType = CommandType.StoredProcedure;
            SqlParameter _param = new SqlParameter("@sysuserid",sysuserid);
            _comm.Parameters.Add(_param);
            SqlDataAdapter _da = new SqlDataAdapter(_comm);
            _da.Fill(_table);
 //           DateTime end = new DateTime(DateTime.Now.Ticks);
 //           MessageBox.Show(end.Subtract(start).TotalMilliseconds.ToString());
        }

The SqlConnection is not closed. If the SqlConnection goes out of scope, it won't be closed. Therefore, you must explicitly close the connection by calling Close or Dispose. Close and Dispose are functionally equivalent.

If the connection pooling value Pooling is set to true or yes, the underlying connection is returned back to the connection pool. On the other hand, if Pooling is set to false or no, the underlying connection to the server is actually closed.

This could be the reason why the memory goes up.

To use SqlConnection properly, you can follow this:

using (SqlConnection connection = new SqlConnection(connectionString))
    {

        // Do work here; connection closed on following line.
    }

Please read the MSDN for details

Please also check if the UI objects you're using should be disposed explicitly as UI object will allocate native handles.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top