803*_* DX 8 c# wpf xaml garbage-collection memory-leaks
我写了一个测试程序,其中单个Button
在XAML中定义为a的内容Window
.在窗口加载时,以Button
编程方式替换为窗口的内容,并且引用它的字段也由Button
我以编程方式创建的另一个字段替换.之后我Button
使用弱引用跟踪两个对象,并以1/10秒的间隔轮询IsAlive
每个对象的属性.在第IsAlive
一次调用轮询方法的第一次检查之前,我也删除了以编程方式定义的生根引用Button
.
运行此代码的期望是,尽管C#垃圾收集的时间不确定,但两个Button
对象最终都会被报告为垃圾收集.尽管以编程方式定义Button
了这种行为,通常在1/2分钟内,但从Button
不收集XAML .看到这种行为,我已经让程序运行了十多分钟.
谁能告诉我为什么Button
没有收集XAML 对象?特别是,我想知道垃圾收集阻止引用的位置,它是在我的代码中还是在WPF实现中.也许它在XAML加载对象中.我在看某种内存泄漏吗?
上面描述的程序包括在下面以供参考.
MainWindow.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>
Run Code Online (Sandbox Code Playgroud)
MainWindow.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));
}
}
}
Run Code Online (Sandbox Code Playgroud)
App.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" />
Run Code Online (Sandbox Code Playgroud)
该按钮未被收集,因为它在 Window 名称范围内被强烈引用:
但它不应该被识别为内存泄漏,因为您应该在范围内重新注册新按钮:
//...
INameScope scope = NameScope.GetNameScope(this);
scope.UnregisterName("btn");
btn = new System.Windows.Controls.Button();
Content = btn;
scope.RegisterName("btn", btn);
//...
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
483 次 |
最近记录: |