- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
所以我使用 WPF 3.5 和 MVVM + DataTemplate 方法在 GUI 上加载 2 个 View 。我在内存分析时观察到,作为项目控件的项目容器的一部分生成的项目被固定到内存中,即使在卸载 View 后也不会被 GC 处理!
我刚刚进行了测试,发现即使是最简单的代码也可以重现......你们可以自己检查一下。
XAML:
<Window x:Class="ContentControlVMTest.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ContentControlVMTest"
Title="Window2" Height="300" Width="300">
<DockPanel LastChildFill="True">
<CheckBox Click="CheckBox_Click" Content="Test1?"
DockPanel.Dock="Top" Margin="5"/>
<ContentControl x:Name="contentControl">
<ContentControl.Resources>
<DataTemplate DataType="{x:Type local:Test3}">
<TextBlock Text="{Binding C}" Margin="5"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Test1}">
<DockPanel LastChildFill="True" Margin="5">
<TextBlock Text="{Binding A}"
DockPanel.Dock="Top"
Margin="5"/>
<ListBox ItemsSource="{Binding Bs}"
DisplayMemberPath="B"
Margin="5"/>
</DockPanel>
</DataTemplate>
</ContentControl.Resources>
</ContentControl>
</DockPanel>
</Window>
代码隐藏:
public class Test3
{
public string C { get; set; }
}
public class Test2
{
public string B { get; set; }
}
public class Test1
{
public string A { get; set; }
private List<Test2> _Bs;
public List<Test2> Bs
{
get
{
return _Bs;
}
set
{
_Bs = value;
}
}
}
public partial class Window2 : Window
{
public Window2()
{
InitializeComponent();
this.KeyDown += Window_KeyDown;
}
private void Window_KeyDown
(object sender, System.Windows.Input.KeyEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl))
if (Keyboard.IsKeyDown(Key.LeftShift))
if (Keyboard.IsKeyDown(Key.LeftAlt))
if (Keyboard.IsKeyDown(Key.G))
{
GC.Collect(2, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(2, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(3, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers();
GC.Collect(3, GCCollectionMode.Forced);
}
}
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
if (((CheckBox)sender).IsChecked.GetValueOrDefault(false))
{
var x = new Test1() { A = "Test1 A" };
x.Bs = new List<Test2>();
for (int i = 1; i < 10000; i++ )
{
x.Bs.Add(new Test2() { B = "Test1 B " + i });
}
contentControl.Content = x;
}
else
{
contentControl.Content = new Test3() { C = "Test3 C" };
}
}
}
我通过 Left Shift + Alt + Ctrl + G 执行强制 GC。Test1
或 Test3
View 和 View 模型的所有项目在正确卸载后都死掉了。所以这符合预期。
但在 Test1
模型(具有 Test2
对象)中生成的集合仍然固定在内存中。它表明该数组是列表框的项目容器使用的数组,因为它显示了列表框中的去虚拟化项目的数量!当我们在 Test1
View 模式下最小化或恢复 View 时,这个固定数组会改变它的大小!一次是 16 个项目,下一次是 69 个项目。
这意味着 WPF 执行项目控件中生成的项目的固定!谁能解释一下?这有什么明显的缺点吗?
非常感谢。
最佳答案
该问题是由于绑定(bind)机制未能完全释放实际已绑定(bind)显示在屏幕上的列表项引起的。最后一点几乎可以肯定是为什么您在不同的运行中看到不同数量的“孤立”实例。滚动列表越多,产生的问题就越多。
这似乎与 a bug report that I submitted over a year ago 中描述的同一类潜在问题有关因为固定根和固定实例树是相似的。 (要以方便的格式查看此类详细信息,您可能需要获取一份更高级的内存分析器的副本,例如 ANTS Memory Profiler。)
真正的坏消息是,您的孤立实例在窗口本身消亡后被固定,因此如果没有我在 WinForms 场景中必须使用的相同类型的 hack 来强制清理,您可能无法清理它们-结合私有(private)。
所有这一切中唯一的好消息是,如果您可以避免绑定(bind)到嵌套属性,那么问题就不会发生。例如,如果您将 ToString() 重写添加到 Test2 以返回其 B 属性的值并从您的列表框项目中删除 DisplayMemberPath,问题就会消失。例如:
public class Test2
{
public string B { get; set; }
public override string ToString()
{
return this.B;
}
}
<ListBox ItemsSource="{Binding Bs}"
Margin="5"/>
关于c# - GC 的固定实例 - 无法从我的托管代码中追踪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9378183/
我正在开发一个网站,在不使用任何第三方 API 的情况下使用 Firebase 云消息传递(Chrome 和 Firefox 浏览器)向我的订阅者发送推送通知。推送通知发送工作正常,但我不知道“如何跟
我在尝试追踪此 OutOfMemoryError 时遇到了非常糟糕的时间,非常感谢您的帮助。我的应用程序分为架构部分和一个模块,该模块公开一些基本的 REST WS 以及 Hibernate 进行的数
在 Android 操作系统源代码中(路径:/drivers/staging/android/binder_trace.h),我们有一个名为 binder_trace.h 的文件,并且在 /drive
我正在查看我的 CakePHP 应用程序的 error.log,并看到我定期收到此类信息: 2011-07-28 14:49:39 Warning: Warning (2): Missing argu
我收到了有关我的应用程序中内存泄漏的报告,但我无法准确追踪到底发生了什么。我有一个功能可以取出旧 View 并交换新 View 。我没有使用 NavControllers 或任何 @propertie
这是真气! >_< 我编写了一个庞大而复杂的 Haskell 库。我写了一个小测试程序,到目前为止,我已经花了大约 8 个小时试图弄清楚为什么它一直在我身上崩溃。有时 GHC 会提示“奇怪的封闭类型”
是否有系统的方法来调试导致组件在 React 中重新渲染的原因?我放置了一个简单的 console.log() 来查看它渲染了多少次,但我很难弄清楚是什么导致组件渲染多次,即在我的情况下(4 次)。是
我已经升级到 Django 1.4,现在当我运行我的开发服务器时,我收到以下警告: /home/flc/venvs/myprj/lib/python2.6/site-packages/django/v
我有一个 Web 应用程序在某处存在内存泄漏,但我无法检测到它。我已经尝试过 Chrome 开发者工具,通常效果很好,但我无法追踪负责的代码行。 Chrome 工具给了我太多信息,我无法将内存中的对象
直接从标记调用函数的好处之一是更容易跟踪所调用的内容。我想知道是否有浏览器插件或其他东西支持附加(绑定(bind))到元素的每个事件的“Goto javascript 源函数”。理想情况下,这会将我带
我在工作中使用 darcs 已经一年多了,但我一直在问自己同样的问题: 跟踪导致两个补丁之间依赖的代码行/文件/代码更改的最佳方法是什么?目前我的做法如下: 我使用 darcs changes -i
我知道以前有人问过此类问题,但我无法解决我的疑问。我有一个简单的黑白棋引擎(实际上它玩得很好),它使用下面的类来获得最佳棋步: import java.util.*; import java.util
上下文:我们正在构建用于快速交付 WPF 应用程序的框架。该框架使用 Autofac 作为 IoC 容器,还使用 Prism v1 中的区域。我们正在使用 Microsoft 的并行扩展来安排任务
有什么追踪东西的技巧吗?技术?任何可用于检查函数 x 的调用者的工具(调用堆栈的某些部分显示为 ??? 或被跳过)。 --track-origins=yes 是否会使速度变慢(当我尝试这样做时,我使用
我有一个基于 KnockoutJS 2.2.1 创建的 jQuery 网格插件。到目前为止它进展顺利,但是当插件在一个元素上初始化时,'computed' loadGrid 方法调用 3 次。 为了说
我是这种开发的新手。我正在尝试创建一个涉及 GPS 跟踪的 android 应用程序。我正在使用 Nutiteq,因为我必须使用 openstreetmap 作为默认 map 。请帮助我。 最佳答案
我希望用户能够通过我的应用程序之一跟踪他们的 friend 。该应用程序适用于音乐节。 我一直在想办法做到这一点: 让用户为设备设置昵称(与 UDID 关联),并让用户通过昵称将彼此添加到“好友列表”
有没有办法找到所有者或域名示例,如果我给谷歌的IP,我的工具发现谷歌的IP,这应该以编程方式完成地址最喜欢的编程语言将是VC++其他语言也不是问题 最佳答案 您正在寻找的关键字似乎是WHOIS 通常可
我的 VC++ 项目中有几个包含大量类的 map ,其中一些默认可构造,另一些则不能。尝试构建时,出现“没有合适的默认构造函数可用”错误。问题是错误被列为发生在 map.cpp 的第 173 行,这是
我平均工作(约 20k 行代码,Objective-C 与 C++ 混合),我正在努力寻找 EXC_BAD_ACCESS 错误。 我已经尝试了所有常见的技术(比如启用 NSZombie、guard e
我是一名优秀的程序员,十分优秀!