使用更新的.NET 4.0,我发现了一个奇怪的内存泄漏,可以通过下面的示例代码来再现。
<DropShadowEffect>,其Color依赖属性绑定到App中的一个属性。DropShadowEffect 资源时,才会发生这种情况。不发生在SolidColorBrush 上,其 Color 也绑定到相同的源。非常感谢有人能告诉我为什么这个泄漏发生在DropShadowEffect上,而不是在SolidColorBrush上。
App.xml
<Application x:Class="WpfSimple.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<!--this one make GC unable to collect LeakWindow-->
<DropShadowEffect x:Key="AppDropShadowColor"
Color="{Binding Source={x:Static Application.Current}, Path=DropShadowColor, Mode=OneWay}" />
<!--this one does not leak-->
<SolidColorBrush x:Key="AppBackground"
Color="{Binding Source={x:Static Application.Current}, Path=DropShadowColor, Mode=OneWay}" />
</Application.Resources>
</Application>App.xml.cs启动MainWindow并为属性DropShadowColor实现INotifyPropertyChanged。
public partial class App : Application, INotifyPropertyChanged
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
// start main window
var mainWindow = new MainWindow();
mainWindow.Show();
}
private Color _dropShadowColor = Colors.Blue;
public Color DropShadowColor
{
get { return _dropShadowColor; }
set {
_dropShadowColor = value;
OnPropertyChanged("DropShadowColor");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); }
}
}MainWindow.xml和MainWindow.xml.cs有一个按钮来创建LeakWindow,如下所示。
var win = new LeakWindow {Owner = this};
win.Show();还有一个按钮可以做GC.Collect();
LeakWindow.xml
<Window x:Class="WpfSimple.LeakWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Leak" Height="300" Width="300">
<Grid>
<!--leak-->
<Border Width="200" Height="200" BorderThickness="1" BorderBrush="Black" Effect="{StaticResource AppDropShadowColor}"/>
<!--no leak if comment out above and uncomment below-->
<!--<Border Width="200" Height="200" BorderThickness="1" BorderBrush="Black" Background="{StaticResource AppBackground}"/>-->
</Grid>
</Window>LeakWindow.xml.cs
public partial class LeakWindow : Window
{
public LeakWindow()
{
InitializeComponent();
}
~LeakWindow()
{
Debug.WriteLine("LeakWindow finalized");
}
}更新
OneTime也无济于事。DynamicResource没有帮助。进一步的调查表明,泄漏是由EventHandler引用从DropShadowEffect到Border.Effect造成的。可能是由于DropShadowEffect中的绑定导致的更改通知。
然而,奇怪的是,为什么这只发生在Border.Effect Border.Background**?**上,而不发生在上。
工作站
将x:Shared=false添加到app.xml中的<DropShadowEffect>可以解决这一问题。我现在可以拥有应用程序范围的定义资源,但失去了内存效率。
发布于 2015-07-31 08:59:19
我认为问题是由DropShadowEffect连接到可视树的方式引起的。将DropShadowEffect移动到控件模板中,而不是将其作为资源,可能会解决泄漏问题,但这样您就失去了共享资源.
发布于 2015-07-31 12:55:49
<Controls:MetroWindow x:Class="WpfApplication.Window"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
ShowMaxRestoreButton="False"
ResizeMode="NoResize" ShowMinButton="False"
EnableDWMDropShadow="True" WindowStartupLocation="CenterScreen" Name="Window"
Height="400" Width="567">您可以尝试导入mah应用程序,它有带有一行EnableDWMDropShadow="True“行的阴影窗口。
https://stackoverflow.com/questions/31735010
复制相似问题