Click here to Skip to main content
15,886,782 members
Please Sign up or sign in to vote.
4.00/5 (2 votes)
See more:
Hi
I have a simple progress-bar like shape used to notify the user that some operation is in progress. The shape extends the Shape class and internally uses a DispatcherTimer. Each time the timer elapses new geometry item is added to the shape. It also has the IsRunning dependency property used to start or stop the timer.

The shape is used on two views in a MVVM application. The application uses the TemplateSelector to show the correct view based on the current viewmodel. The views(user controls) which are using the shape bind its IsRunning d.p. to IsRunning property on the viewmodel.

HTML
<control:SimpleWaitControl IsRunning={Binding Path=IsRunning} />


Below is the sample code used to create a template selector

HTML
<selector:TemplateSelector x:Key="TemplateSelector">
   <selector:TempateSelector.View1Template>
      <DataTemplate>
         <view:View1 />
      </DataTemplate>
   </selector:TempateSelector.View1Template>
   ... templates for other views
</selector:TemplateSelector>


While i was debugging some stuff I added logging to Start and Stop methods of the shape(methods called when the value of IsRunning dependency property is changed) amd found out that the shape does not get garbege collected when the view get removed from the window. The output window in V.S indicates that each time the View1 or View2 is shown new shape is constructed and started but with it all the shapes that were constructed previously are started. So when the View1 is shown for the 5th time one new SimpleWaitControl is constructed but 5 of them are started. When the View1 is removed for the 5th time all 5 of them get stopped. What am I missing? As far as I know the controls can not (and need not) be disposed. Any idea will appreaciated.

Uros
Posted

1 solution

You are missing to understand that the actual garbage collection may happen not when you expected (by whatever reason), but it may happen some time later. I cannot believe it is not garbage-collected at all. I think, it happens, but later. You did not mention it in your description though.

The operation of GC is driven by the reachability of objects. The actual call of the object destructors and the act of reclaiming memory cannot be predicted bu the application (by the way, this is the reason why destructors are rarely written in the typical .NET applications, usually this is not needed and can created some problems of race conditions type), but it happens when some object becomes unreachable.

By the way, this is not so trivial criterion as you might think. For example, if object A references object B, object B references object C, and C reference A, this cyclic dependency does not prevent GC from figuring out that all objects should be garbage-collected if there are no other referenced to them. This is easy to check up by a simple experiment.

You can find the detail of reachability and garbage collection here: http://en.wikipedia.org/wiki/Garbage_collection_%28computer_science%29[^].

Now, you should not think that such thing as memory leak is impossible in a memory-managed system like CLR. It is quite possible, but the problem here is understanding what is a memory leak. For further detail, please see my past answers on this and related topics:
Garbage collectotion takes care of all the memory management[^],
deferring varirable inside the loop can cuase memory leak?[^],
Best way to get rid of a public static List Causing an Out of Memory[^],
Memory management in MDI forms[^].

Good luck,
—SA
 
Share this answer
 
v2
Comments
BillW33 3-Jan-13 17:00pm    
Very fine answer; +5
Sergey Alexandrovich Kryukov 3-Jan-13 17:02pm    
Thank you very much,
—SA
koleraba 4-Jan-13 15:22pm    
Hi Sergey
Thank you for your quick reply. I know that GC runs can not be predicted so I (just for debugging purposes) added a call to GC.Collect() after the current view is changed but it did not help.
Sergey Alexandrovich Kryukov 4-Jan-13 15:54pm    
This is also not recommended, for majority of cases. You see, if there are some reachable object, GC will not collect them anyway; and the collection is done using some optimized schedule. Perhaps, GC.Collect() can be used if your memory consumption pattern is rather unusual, but, for you information, this method does not guarantee that GC collects the unreachable objects on this comment. This is rather the recommendation. It's easy to check up (using destructors written for this purpose) if GC listens to this command or not.

Maybe you will be surprised: usually, GC ignores these calls!

So, are you going to accept my answer formally (green button)?

—SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900