WPF代码中的内存泄漏

时间:2014-04-24 15:35:03

标签: c# .net wpf memory-leaks

我有这个代码,每次都是"主菜单"单击项目。它基本上填充了一个子菜单堆栈面板" buttoned"用户控制。

    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();

    }

我发现的事情是,每次执行此代码时,进程中的内存会上升几个K并且永远不会让人失望。我从阅读中发现的是,强制垃圾收集可以提供帮助,但确实如此,但我也认为这不是一个好的做法,并且想要找到实际发生泄漏的地方。

要说明问题,如何捕获泄漏,代码是否是原因?

谢谢。

GetMenuItems来自这个类。

 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;
            }
        }

1 个答案:

答案 0 :(得分:0)

在您的代码中:

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());
        }

SqlConnection未关闭。如果SqlConnection超出范围,则不会被关闭。因此,您必须通过调用Close或Dispose显式关闭连接。关闭和处置在功能上是等效的。

如果连接池值Pooling设置为true或yes,则将基础连接返回到连接池。另一方面,如果Pooling设置为false或no,则实际上将关闭与服务器的基础连接。

这可能是内存增加的原因。

要正确使用SqlConnection,您可以按照以下步骤操作:

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

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

请阅读MSDN了解详情

请同时检查您使用的UI对象是否应明确处理,因为UI对象将分配本机句柄。