SL 4 / CSLA 3.8.x and anonymous methods for DataPortal.FetchCompleted

SL 4 / CSLA 3.8.x and anonymous methods for DataPortal.FetchCompleted

Old forum URL: forums.lhotka.net/forums/t/9209.aspx


Jack posted on Thursday, July 15, 2010

I just started using ANTS Memory Profiler 6 (really cool) which allows profiling a SL4 application.  I am quickly realizing how awful I was with events and why I have huge memory leaks all over the place.

Nonetheless I have improved my framework and things are much better.  However I am still finding that I am not able to GC many objects because they are still attached to the FetchCompleted event.
I thought I was doing the recommended approach for fetching my data but I'm not so sure now.  I'm doing the same thing all over the place:

 public static void GetObjectDataEntryManager(int objectId, EventHandler<DataPortalResult<ObjectDataEntryManager >> handler)
 {
  var dp = new DataPortal<ObjectDataEntryManager >();
  dp.FetchCompleted += handler;
  dp.BeginFetch(new SingleCriteria<ObjectDataEntryManager, int>(objectId));
 }

In my handler (which is in my VM) I'm checking for errors, pulling out the object and doing some processing.  I believe the issue is that I'm not de-attaching handler from dp.FetchCompleted and so it never goes away.  I can't because I've done everything with anonymous methods (http://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c)

 private void GetDataEntryManager()
        {
            ObjectDataEntryManager.GetObjectDataEntryManager(ObjectId, (o, e) =>
            {
                if (e.Error != null) MessageBox.Show(e.Error.Message, "Unable to initialize DataEntryManager", MessageBoxButton.OK);
                _dataEntryManager = e.Object;
   ...
                RaisePropertyChanged("DataEntryManager");
            });
           
        }

So what I'm seeing is that my view and viewModel can't be garbage collected because they are still attached to my compressed proxy and the CSLA.WCFPortal.WCFPortalClient. 

 


Now likely I just picked up a bad habit way back when after copying code from the first versions of the Inventory or first SL sample app and didn't even notice.  I'm just curious if anyone has suggestions as to the cleanest way to get out of this mess as it is all over the place in my application.

Any help appreciated.

Thanks

jack

 

RockfordLhotka replied on Thursday, July 15, 2010

When you handle an event, that causes a reference to be established from the object that raises the event to the object handling the event.

In this case the object raising the event is the data portal - and if you follow the chain all the way down that'll end up being the actual WCF proxy object used to talk to the server. The actual event you are handling is probably from the CSLA WcfProxy (CompressedProxy) or the DataPortal<T> object.

Neither of those objects is scoped beyond your factory method, so they shouldn't stick around in memory (very long at least) after your factory method completes.

In other words, it shouldn't matter if you unhook the event or not, because the event source (the thing holding a reference to your anonymous method) should just go away.

Clearly the instance of DataPortal<T> should go away - you can see its scoping in your code. If the CompressedProxy instance isn't going away then that's a bug - either in CSLA or your code - where something must be holding a reference to the proxy object.

I just scanned through the data portal code again though, and it creates a new instance of the proxy for every DataPortal<T>, and I can't see any static references to the proxy object, so it should go away when the DataPortal<T> instance is GCed.

Copyright (c) Marimer LLC