Memory Leak with WCF Service

4 posts, 0 answers
  1. Michele
    Michele avatar
    426 posts
    Member since:
    Jun 2009

    Posted 15 Jun 2010 Link to this post

    Hello,
    I'm really getting mad about this... I'm currently developing a SL4 new project and I started to look at memory usage...
    I keep the thing simple, I've got a button that open up a UserControl with a dropdown filled via WCF (HTTP

    what I got using windbg is the following :

    0:027> !gcroot 073de658   
    Note: Roots found on stacks may be false positives. Run "!help gcroot" for  
    more info.  
    Scan Thread 5 OSTHread b58  
    Scan Thread 20 OSTHread 5cc  
    Scan Thread 21 OSTHread ff4  
    Scan Thread 24 OSTHread 11c4  
    Scan Thread 25 OSTHread 1004  
    DOMAIN(060F6AC8):HANDLE(AsyncPinned):38428fc:Root:  074c0084(System.Threading.OverlappedData)-> 
      073ec84c(System.Threading.IOCompletionCallback)-> 
      073ea61c(System.Net.Sockets.SocketAsyncEventArgs)-> 
      073e9e6c(System.Net.Sockets.Socket+StaticConnectAsyncState)-> 
      073e9dd8(System.Net.Sockets.SocketAsyncEventArgs)-> 
      073e93d0(System.ServiceModel.Channels.SocketConnectionInitiator+ConnectAsyncResult)-> 
      073e9160(System.ServiceModel.Channels.ConnectionPoolHelper+EstablishConnectionAsyncResult)-> 
      073e90fc(System.ServiceModel.Channels.ClientFramingDuplexSessionChannel+OpenAsyncResult)-> 
      073e90cc(System.ServiceModel.Channels.CommunicationObject+OpenAsyncResult)-> 
      073e907c(System.ServiceModel.Channels.CommunicationObject+OpenAsyncResult)-> 
      073e8e24(System.ServiceModel.Channels.ServiceChannel+SendAsyncResult)-> 
      073de624(System.ServiceModel.ClientBase`1+AsyncOperationContext[[PROJECT.DO.ServiceUtility.IServiceUtility, PROJECT.DO]])-> 
      073de5f0(System.Threading.SendOrPostCallback)-> 
      073cb83c(PROJECT.DO.ServiceUtility.ServiceUtilityClient)-> 
      073de658(PROJECT.DO.ServiceUtility.ServiceUtilityClient+ServiceUtilityClientChannel)  
     

    I've tried all in my knowledge to close this .... but with no luck....
    Here's what I'm doing :

    MainPage :

       private void btnLoadUtility_Click(object sender, RoutedEventArgs e)  
            {  
                Telerik.Windows.Controls.RadWindow w = new Telerik.Windows.Controls.RadWindow();  
     
                Utility.UtilityInquiry inquiry = new Utility.UtilityInquiry();  
     
                w.Content = inquiry;  
                w.Height = 800;  
                w.Width = 1000;  
     
                w.Closed += new EventHandler<Telerik.Windows.Controls.WindowClosedEventArgs>(w_Closed);  
                w.Show();  
            }  
     
            void w_Closed(object sender, Telerik.Windows.Controls.WindowClosedEventArgs e)  
            {  
                var window = sender as RadWindow;  
     
                window.Closed-=new EventHandler<WindowClosedEventArgs>(w_Closed);  
     
                if (window.Content is IDisposable)  
                    ((IDisposable)window.Content).Dispose();  
     
                window.Content = null;  
     
                GC.Collect();  
                GC.WaitForPendingFinalizers();  
                GC.Collect();  
     
            } 

    and in the UtilityInquiry :

        #region Variables  
            private ServiceUtilityClient clientUtility;  
            #endregion  
     
            #region CTor  
            public UtilityInquiry()  
            {  
                InitializeComponent();  
            }  
            #endregion  
     
            #region Events  
            private void UserControl_Loaded(object sender, RoutedEventArgs e)  
            {  
                clientUtility = ProxyFactory.GetUtilityClient();  
     
                clientUtility.GetStoreProcedureFromTipoCompleted += new EventHandler<GetStoreProcedureFromTipoCompletedEventArgs>(clientUtility_GetStoreProcedureFromTipoCompleted);  
                clientUtility.GetStoreProcedureFromTipoAsync(-1);  
            }  
     
            private void clientUtility_GetStoreProcedureFromTipoCompleted(object sender, GetStoreProcedureFromTipoCompletedEventArgs e)  
            {  
                if (e.Error == null)  
                {  
                    cbStoreProcedure.ItemsSource = e.Result;  
                }  
                else  
                {  
                    MessageBox.Show(e.Error.Message);  
                }  
            }  
          
    public void Dispose()  
            {  
                clientUtility.GetStoreProcedureFromTipoCompleted -new EventHandler<GetStoreProcedureFromTipoCompletedEventArgs>(clientUtility_GetStoreProcedureFromTipoCompleted);  
                clientUtility.CloseAsync();  
     
                ((IDisposable)clientUtility.ChannelFactory).Dispose();  
                clientUtility = null;  
     
               
                this.Loaded -new RoutedEventHandler(UserControl_Loaded);  
                this.SizeChanged -new SizeChangedEventHandler(UserControl_SizeChanged);  
                cbStoreProcedure.SelectionChanged -new Telerik.Windows.Controls.SelectionChangedEventHandler(cbStoreProcedure_SelectionChanged);  
                btnExport.Click -new RoutedEventHandler(btnExport_Click);  
                cbStoreProcedure.ItemsSource = null;  
     
                spanel.Children.Clear();  
     
                foreach (UIElement ui in gvContent.Children)  
                {  
                    if (ui is IDisposable)  
                        ((IDisposable)ui).Dispose();  
                }  
     
                gvContent.Children.Clear();  
                LayoutRoot.Children.Clear();  
            }  
     
            ~UtilityInquiry()  
            {  
                int t = 0;  
            } 

    What I'm missing? the ~UtilityInquiry is not showed the first time I close the RadWindow, starts from the second but I'm not able to remove the WCF call (or better I think it's left open)

    Any suggestion?
    Thanks



  2. Konstantina
    Admin
    Konstantina avatar
    2332 posts

    Posted 18 Jun 2010 Link to this post

    Hello Paolo,

    Thank you for contacting Telerik Support.

    We looked the attached application and we made some changes. Better practice is to call Collect() and WaitForPendingFinalizers() after closing window, and call them twice, instead of calling GC methods in the close handler of the RadWindow control.

    Attached you can find application that demonstrates how to avoid these memory leaks. We added a Check button. When you close an opened window, you have to click this Check button to check if the object is still alive. There is no need of Close event handler method. In the body of  button2_Click we call GC.Collect()  and  GC.WaitForPendingFinalizers() twice to be sure that the object isn't alive. This is a specific behavior of Silverlight GarbageCollector.

    This works if you don't drag the control. We are aware of that RadWindow has memory leak when you drag it and we are working on it. We will provide a fix in one of our future releases.

    I hope this information helps. I will be glad to assist you further.

    Sincerely yours,

    Konstantina
    the Telerik team

     

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
  3. Michele
    Michele avatar
    426 posts
    Member since:
    Jun 2009

    Posted 18 Jun 2010 Link to this post

    Hello Konstantina ,
    I know I've send you two thread about memory leak.... this one if related to WCF and not to the RadGridView as I've wrote in the ticket.... thanks...

    Paolo
  4. Miroslav Nedyalkov
    Admin
    Miroslav Nedyalkov avatar
    1718 posts

    Posted 23 Jun 2010 Link to this post

    Hi Paolo,

     In your sample code you are calling the GC while you still have reference to the window, so it will not be collected in this moment. If you want to make sure your instance will be garbage-collected you should perform the calls to GC.Collect and GC.WaitForPendingFinilizers after the Closed handler finishes. 

    Anyway I don't think you should depend on whether visual elements are garbage-collected or not to perform other kinds of clean-up. You could perform them in the Closed event handler and don't care is the window really destroyed or not.

    Hope this information is helpful.

    All the best,
    Miroslav Nedyalkov
    the Telerik team
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items
Back to Top