Tôi đã đoạn mã sau, mà sẽ tạo ra một OutOfMemoryException
khi chạy:Thay thế cho GarbageCollector là gì?
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;
}
}
Trường hợp Graphics_Canvas
được định nghĩa như sau:
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);
}
}
Và XAML để tạo ra các Window
là như thế này:
<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>
Bây giờ, đây chỉ là ví dụ minh họa quan điểm của tôi, đó là tôi không hiểu theo cách khác là sử dụng Garbage Collector ...
Nếu bạn chạy chương trình và tiếp tục di chuyển chuột qua Graphics_Canvas
, việc sử dụng bộ nhớ sẽ tạo và xây dựng và xây dựng cho đến khi bạn nhận được OutOfMemoryException
. Nếu bạn thêm vào GC.Collect()
nơi tôi đã nhận xét nó, điều này không xảy ra (mặc dù bộ nhớ tăng lên một lượng nhỏ, vì những lý do ngoài tôi và hy vọng liên kết với vấn đề của tôi) và chương trình tiếp tục hoạt động.
Vì vậy, tại sao GC
không khởi động và xóa bộ nhớ này và dừng ngoại lệ xảy ra? Nếu tôi đang làm một số lỗi rất cơ bản, tôi sẽ rất vui vì một người nào đó đã chỉ ra cho tôi để tôi có thể vượt qua điều này.
Tôi đã thấy nhiều lần trên trang web này và những lời khuyên khác từ các lập trình viên nói rằng "không bao giờ sử dụng Bộ sưu tập rác". Tôi muốn phù hợp với thực hành tốt nhất, nhưng tôi không thấy trong những tình huống như thế này những gì khác tôi có thể làm.
Hoàn toàn trung thực; Tôi thấy nó kỳ lạ, rằng hệ thống sẽ ném một 'OutOfMemoryException' ** trước khi thử một' GC.Collect() '. Chỉ cần hai xu của tôi. – Nolonar
Đợi, mã trước tiên là * xóa * một phần tử rồi thêm một phần tử khác. Đó là tốt. –
Điều gì về phần đầu tiên xóa dữ liệu hiển thị hiện tại? – RichieHindle