gpt4 book ai didi

c# - 垃圾收集器的替代品是什么?

转载 作者:太空狗 更新时间:2023-10-29 20:17:25 24 4
gpt4 key购买 nike

我有以下代码,运行时会产生一个OutOfMemoryException:

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;
}
}

其中 Graphics_Canvas 定义如下:

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);
}
}

创建 Window 的 XAML 是这样的:

<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>

现在,这只是一个例子来说明我的观点,我不明白这里有什么可以替代使用垃圾收集器...

如果您运行该程序,并不断将鼠标移到 Graphics_Canvas 上,内存使用会不断增加,直到出现 OutOfMemoryException。如果你在我注释掉的地方添加 GC.Collect(),这不会发生(尽管内存确实增加了少量,出于我以外的原因,希望与我的联系起来问题),程序继续运行。

那么,为什么 GC 不启动并清除此内存并阻止异常发生?如果我犯了一些非常根本的错误,我很乐意有人向我指出,这样我就可以改正。

我在这个网站和其他网站上多次看到程序员的建议是“永远不要使用垃圾收集器”。我想遵循最佳实践,但在这种情况下我看不到我还能做什么。

最佳答案

程序无法管理大量内存并不是GC 的错误。在你的程序中你做:

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

//GC.Collect();
}

Tou 为每次鼠标移动添加一个元素,因此增加集合大小。你希望发生什么?

因此,在 90% 情况下,解决此类问题的方法是重新构建您的代码。

示例:

您几乎不可能每次都需要在 MouseMove 上将一个新元素添加到视觉的子集合中。可能是重用已经存在的案例。

建议明确使用GC,但有时我们需要使用它。但是,我再说一遍,我很难相信在这种情况中您需要以那种方式管理程序。

关于c# - 垃圾收集器的替代品是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15611404/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com