FluidMoveBehavior memory leak + bug
-
Friday, September 10, 2010 9:10 PM
Im pretty sure I've discovered a memory leak with the FluidMoveBehavior.
The static TagDictionary in FluidMoveBehaviorBase is holding references and creating a memory leak.Who do I need to contact to fix this?
All Replies
-
Wednesday, September 15, 2010 4:37 AMAnyone from Microsoft Expression team? Hello??
-
Tuesday, September 21, 2010 7:52 PMhellllooooooo
-
Tuesday, September 21, 2010 8:00 PMHow did you verify that it has a memory leak? Did you run any profiler tools to see what is going on?
My .NET Blog: http://michaelcrump.net -
Wednesday, October 20, 2010 2:01 PM
Yep, we've just discovered this too. We were investigating a memory leak in our app (using windbg + SL sos.dll) and found that, as you said, the FluidMoveBehavior.TagData stuff is holding on to (in our case) the last thing that used a FluidMoveBehavior.
It looks like this is sort of intentional, as the FluidMoveBehavior SetTagBehavior stuff requires static state to communicate. But in our particular case we're not explicitly using any fluid move tagging, so it's simply an annoying leak.
Royston.
Royston Shufflebotham -
Thursday, October 21, 2010 2:54 PM
Hello Michael yes I did run a profiler and verified that yes this is a definite bug.
"The static TagDictionary in FluidMoveBehaviorBase is holding references and creating a memory leak."
I guess in .Net there are no "memory leaks" but there is memory that will never be GC'ed until the application shuts down. In my case every time I visit a piece of the UI that contains a FluidMoveBehavior more memory is grabbed and this continues on and on until i get an outofmemoryexception or i shut down the app
-
Thursday, October 21, 2010 3:04 PMVerified using RedGates memory profiler (which by the way was awesome to use to find this)
-
Tuesday, November 23, 2010 2:01 PM
I have the same problem. I had the FluidMoveBehaviour in an ItemTemplate for a ListBox, and with hundreds of rows and refreshing it quickly killed my app. Started out on a few megs of memory going up to over 500 with a few minutes usage.
I removed the FluidMoveBehaviour and created my own animations where needed. A bit more work but got excactly what I needed.
So yeah, definitely a bug in FluidMoveBehaviour and it should be (for now) used with cation. At least do not use it on a listbox
Ola
-
Tuesday, November 30, 2010 9:49 PMDid you discover this bug in Blend Service Pack 1?
-
Monday, April 18, 2011 7:24 PMI'm seeing the same problem and have profiled it to confirm. Is there any update or workaround?
-
Monday, March 19, 2012 11:45 AM
I managed to work around this problem by attaching the below to the UserControl.Unloaded event:
private void OnUnloaded(object sender, RoutedEventArgs e) { this.Unloaded -= OnUnloaded; this.Children.Clear(); Interaction.GetBehaviors(this) .OfType<FluidMoveBehavior>() .ForEach(b => { b.IsActive = false; b.Detach(); }); }
I verified using RedGate profiler that the FluidMoveBehavior was no longer maintaining references
- Proposed As Answer by Steve Greatrex Monday, March 19, 2012 11:46 AM
-
Thursday, December 13, 2012 6:40 AM
Hi Steve,
I tried using your workaround, but still the TagDictionary instance is alive and causing a leak.
Is there any fix other for this ?
Regards,
Ratish
- Proposed As Answer by Ratish Philip Thursday, December 13, 2012 7:21 AM
- Unproposed As Answer by Ratish Philip Thursday, December 13, 2012 7:21 AM
-
Thursday, December 13, 2012 7:24 AM
Hi,
I have implemented a hack for this issue using Reflection. I am getting the reference to the TagDictionary Collection and invoking it Clear method. I tested this will ANTS memory profiler. Though this is a crude solution, it does its job.
private void OnUnloaded(object sender, RoutedEventArgs e) { this.Unloaded -= OnUnloaded; this.Children.Clear(); foreach (var b in Interaction.GetBehaviors(this).OfType<FluidMoveBehavior>()) { b.IsActive = false; b.Detach(); // HACK: This hack is to clear the TagDictionary collection via reflection as it is holding up references leading // to non-garbage collection of object (a.k.a Leak!) FieldInfo fi = typeof(FluidMoveBehaviorBase).GetField("TagDictionary", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo mi = fi.FieldType.GetMethod("Clear"); mi.Invoke(fi.GetValue(b), null); } }
- Proposed As Answer by Ratish Philip Thursday, December 13, 2012 7:24 AM
- Unproposed As Answer by Ratish Philip Thursday, December 13, 2012 9:03 AM
-
Thursday, December 13, 2012 9:03 AM
Here is a more refined hack! It just removes only the specific object from the dictionary, instead of clearing it.
private void OnUnloaded(object sender, RoutedEventArgs e) { this.Unloaded -= OnUnloaded; DetachFluidMoveBehavior(rootGrid); } private void DetachFluidMoveBehavior(DependencyObject depObj) { if (depObj != null) { foreach (var b in Interaction.GetBehaviors(depObj).OfType<FluidMoveBehavior>()) { b.IsActive = false; b.Detach(); // HACK: This hack is to remove the depObj from the TagDictionary collection using reflection as // the TagDictionary collection is holding up the reference of depObj leading to its non-garbage collection of depObj (a.k.a Leak!) FieldInfo fieldInfo = typeof(FluidMoveBehaviorBase).GetField("TagDictionary", BindingFlags.Static | BindingFlags.NonPublic); if (fieldInfo == null) continue; // Get the TagDictionary object var tagDict = fieldInfo.GetValue(b); // Get the ContainsKey MethodInfo MethodInfo miContainsKey = fieldInfo.FieldType.GetMethod("ContainsKey"); if (miContainsKey != null) { // Does the TagDictionary contain depObj as a key? bool containsKey = (bool)miContainsKey.Invoke(tagDict, new object[] { depObj }); if (containsKey) { // Get the Remove Method Info MethodInfo miRemove = fieldInfo.FieldType.GetMethod("Remove"); if (miRemove != null) { // Remove the depObj from the TagDictionary miRemove.Invoke(tagDict, new object[] { depObj }); } } } } } }
- Proposed As Answer by Ratish Philip Thursday, December 13, 2012 9:03 AM

