gpt4 book ai didi

c# - XAML 按钮在消除引用后未被垃圾回收

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

我编写了一个测试程序,其中在 XAML 中将单个 Button 定义为 Window 的内容。加载窗口后,Button 将以编程方式替换为窗口的内容,引用它的字段也将被我以编程方式创建的另一个 Button 替换。此后,我使用弱引用跟踪两个 Button 对象,并以 1/10 秒的间隔轮询每个对象的 IsAlive 属性。在第一次调用轮询方法时检查 IsAlive 之前,我还清除了对以编程方式定义的 Button 的根引用。

运行此代码的预期是,尽管 C# 垃圾收集的时间不确定,但两个 Button 对象最终都会被报告为垃圾收集。尽管以编程方式定义的 Button 显示此行为(通常在 1/2 分钟内),但 XAML Button 永远不会被收集。看到此行为后,我已经让程序运行了十多分钟。

谁能告诉我为什么没有收集 XAML Button 对象? 特别是,我想知道垃圾回收阻塞引用在哪里,它是在我的代码中还是在 WPF 实现中。也许它在 XAML 加载对象中。我在看某种内存泄漏吗?

将上述程序收录如下,以供引用。

主窗口.xaml:

<Window x:Class="Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="300" Height="150" Loaded="Window_Loaded">
<Button Name="btn" />
</Window>

主窗口.xaml.cs:

namespace Test {
public partial class MainWindow : System.Windows.Window {

private System.WeakReference wr_xamlBtn, wr_programmaticBtn;

public MainWindow() {
InitializeComponent();
}

private void Window_Loaded(object sender, System.Windows.RoutedEventArgs e) {

// Immediately upon the window's loading, create a weak reference to the
// button %btn defined in XAML.
wr_xamlBtn = new System.WeakReference(btn);

// Replace references in %btn and this.Content to the XAML button with
// references to a programmatically-defined button. This would be
// expected to free the XAML button for garbage collection.
btn = new System.Windows.Controls.Button();
Content = btn;

// Create a weak reference to the programmatically-defined button, so that
// when (strong) references to it are removed, it will be eligible for
// garbage collection.
wr_programmaticBtn = new System.WeakReference(btn);

// Provides a polling mechanism to see whether either the XAML button or
// the programmatically-defined button has been collected.
var dt = new System.Windows.Threading.DispatcherTimer();
dt.Tick += Poll;
dt.Interval = System.TimeSpan.FromMilliseconds(100);
dt.Start();
}

void Poll(object sender, System.EventArgs e) {

// If the programmatically-defined button hasn't had its references
// removed yet, this does so. This makes it eligible for garbage
// collection.
if (btn != null)
Content = btn = null;

// Uses the console to show a timestamp and the state of collection of the
// XAML button and the programmatically-defined button.
System.Console.WriteLine(
string.Format(
"XAML button {0}, Programmatically-defined button {1} @ {2}",
wr_xamlBtn.IsAlive ? "Alive" : "Collected",
wr_programmaticBtn.IsAlive ? "Alive" : "Collected",
System.DateTimeOffset.Now));
}
}
}

应用程序.xaml:

<Application x:Class="Test.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml" />

最佳答案

按钮未被收集,因为它在 Window 名称范围内被强引用:

MemProfiler snapshot

但它不应该被识别为内存泄漏,因为您应该重新注册您在范围内的新按钮:

//...
INameScope scope = NameScope.GetNameScope(this);
scope.UnregisterName("btn");
btn = new System.Windows.Controls.Button();
Content = btn;
scope.RegisterName("btn", btn);
//...

关于c# - XAML 按钮在消除引用后未被垃圾回收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8142084/

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