What is the alternative to GarbageCollector?

I have the following code that will throw an OutOfMemoryException on startup:

 public partial class MainWindow : Window { private DrawingVisual myVisual = new DrawingVisual(); public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { myVisual = GetVisual(); graphicsCanvas.AddVisual(myVisual); } private void Graphics_Canvas_MouseMove(object sender, MouseEventArgs e) { //get the data visual: DrawingVisual tempVisual = GetVisual(); //first clear the current display data: graphicsCanvas.RemoveVisual(myVisual); //get the data visual: myVisual = tempVisual; graphicsCanvas.AddVisual(myVisual); //GC.Collect(); } private DrawingVisual GetVisual() { double width = graphicsCanvas.ActualWidth; double height = graphicsCanvas.ActualHeight; DrawingVisual dV = new DrawingVisual(); Rect clipRect = new Rect(0, 0, width, height); dV.Clip = new RectangleGeometry(clipRect); using (DrawingContext dC = dV.RenderOpen()) { RenderTargetBitmap rTB = new RenderTargetBitmap((int)width, (int)height, 96, 96, PixelFormats.Pbgra32); if (rTB.CanFreeze) { rTB.Freeze(); } dC.DrawImage(rTB, clipRect); } return dV; } } 

Where a Graphics_Canvas is defined as follows:

 class Graphics_Canvas : Canvas { private List<DrawingVisual> visuals = new List<DrawingVisual>(); protected override int VisualChildrenCount { get { return visuals.Count; } } protected override Visual GetVisualChild(int index) { return visuals[index]; } public void AddVisual(DrawingVisual visual) { visuals.Add(visual); base.AddVisualChild(visual); base.AddLogicalChild(visual); } public bool ContainsVisual(DrawingVisual visual) { return visuals.Contains(visual); } public bool HasVisuals { get { return visuals.Count > 0; } } public void RemoveAllVisuals() { for (int i = 0; i < visuals.Count; i++) { RemoveFromLogicalTree(visuals[i]); } visuals.Clear(); } private void RemoveFromLogicalTree(Visual visual) { RemoveLogicalChild(visual); RemoveVisualChild(visual); } public void RemoveLastVisual() { if (visuals.Count > 0) { int index = visuals.Count - 1; RemoveFromLogicalTree(visuals[index]); visuals.Remove(visuals[index]); } } public void RemoveVisual(DrawingVisual visual) { RemoveFromLogicalTree(visual); visuals.Remove(visual); } } 

And the XAML for creating the Window looks like this:

 <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:csMemoryLeakTestProject" x:Class="csMemoryLeakTestProject.MainWindow" Title="MainWindow" Background="Gray" Height="600" Width="800" WindowStartupLocation="CenterScreen" Loaded="Window_Loaded"> <Grid> <local:Graphics_Canvas Margin="12" Background="White" x:Name="graphicsCanvas" MouseMove="Graphics_Canvas_MouseMove"/> </Grid> </Window> 

Now, this is just an example to illustrate my point, namely that I don’t understand that the alternative here is to use the Garbage Collector ...

If you run the program and continue to move the mouse over Graphics_Canvas , using memory builds, builds and builds until you get an OutOfMemoryException . If you add to GC.Collect() , where I commented on this, this will not happen (although the memory increases by a small amount, for reasons beyond me, and, I hope, is related to my problem), and the program continues to function.

So why doesn't the GC hit and clear this memory and stop the exception from occurring? If I make a very fundamental mistake, I would be very happy if someone pointed me to this so that I could move on.

I have met many times on this website and other programmer tips saying, "Never use a garbage collector." I want to comply with best practice, but I do not see in such situations what else I could do.

+7
source share
2 answers

It is not a GC error that the program cannot manage large memory. In your program, you will do:

 private void Graphics_Canvas_MouseMove(object sender, MouseEventArgs e) { .... //ADD ELEMENTS ON EVERY MOVE ! graphicsCanvas.AddVisual(myVisual); //GC.Collect(); } 

You add an item for each mouse movement to increase the size of the collection. What do you expect?

Thus, in 90% cases, the solution to these problems is the inverse structure of your code.

Example:

It is impossible for you to need MouseMove each time adding a new element to the chidren visual art collection. Maybe this is a case of reusing an existing one.

Unused use of GC not suggested, but sometimes we need to use it. But, I repeat, I can hardly believe that in this case you need to manage the program in this way.

+9
source

I think this describes what can keep your objects alive,

http://msdn.microsoft.com/en-us/library/bb613565.aspx

In short; references in event handlers may still exist.

-one
source

All Articles