2010-01-29 12 views
7

Ho incontrato una situazione in cui sto perdendo memoria non gestita quando il mouse viene spostato sulla mia app WPF. Nello specifico, quando profilo l'applicazione in perfmon o il profilo di memoria di Red Gate, i byte privati ​​aumentano monotonicamente, ma i byte in tutti gli heap gestiti rimangono costanti - il che, credo, significa che l'app ha una perdita non gestita.Perdita non gestita in un'applicazione WPF banale

Ho creato un'applicazione di repro banale, ma non riesco a vedere dove si trova il problema.

L'app è costituita da un controllo ListView con quattro voci. Spostare rapidamente il mouse su questi elementi causa il problema.

Ecco il codice se sei interessato a riprodurre il problema: non è bello, ma è semplice.

Grazie


Edit: Ho creato un Microsoft Connect issue per questo problema.


App.xaml

<Application x:Class="WpfLeakRepro.App" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    StartupUri="Window1.xaml"> 
    <Application.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="Generic.xaml" /> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </Application.Resources> 
</Application> 

App.xaml.cs

using System; 
using System.Collections.Generic; 
using System.Configuration; 
using System.Data; 
using System.Linq; 
using System.Windows; 

namespace WpfLeakRepro 
{ 
    /// <summary> 
    /// Interaction logic for App.xaml 
    /// </summary> 
    public partial class App : Application 
    { 
    } 
} 

generic.xaml

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <LinearGradientBrush x:Key="ListItemHover" 
         EndPoint="0,1" 
         StartPoint="0,0"> 
     <GradientStop Color="Aqua" 
         Offset="0" /> 
     <GradientStop Color="White" 
         Offset="1" /> 
    </LinearGradientBrush> 
    <LinearGradientBrush x:Key="ListItemSelected" 
         EndPoint="0,1" 
         StartPoint="0,0"> 
     <GradientStop Color="Blue" 
         Offset="0" /> 
     <GradientStop Color="White" 
         Offset="1" /> 
    </LinearGradientBrush> 
    <VisualBrush x:Key="CheckeredBackground" 
       Viewport="20,20,20,20" 
       ViewportUnits="Absolute" 
       TileMode="Tile" 
       Stretch="Fill"> 
     <VisualBrush.Visual> 
      <Canvas Opacity="5"> 
       <Rectangle Fill="#FF606060" 
          Height="21" 
          Width="21" 
          Canvas.Top="20" /> 
       <Rectangle Fill="#FF606060" 
          Width="21" 
          Height="21" 
          Canvas.Left="20" /> 
       <Rectangle Fill="#FF646464" 
          Height="21" 
          Width="21" 
          Canvas.Left="20" 
          Canvas.Top="20" /> 
       <Rectangle Fill="#FF646464" 
          Width="21" 
          Height="21" /> 
      </Canvas> 
     </VisualBrush.Visual> 
    </VisualBrush> 
    <Style TargetType="{x:Type ListViewItem}"> 
     <Setter Property="Template"> 
      <Setter.Value> 
       <ControlTemplate TargetType="{x:Type ListViewItem}"> 
        <Border Background="{TemplateBinding Background}"> 
         <Grid> 
          <GridViewRowPresenter /> 
         </Grid> 
        </Border> 
        <ControlTemplate.Triggers> 
         <Trigger Property="IsMouseOver" 
           Value="true"> 
          <Setter Property="Background" 
            Value="{DynamicResource ListItemHover}" /> 
         </Trigger> 
         <Trigger Property="IsSelected" 
           Value="true"> 
          <Setter Property="Background" 
            Value="{DynamicResource ListItemSelected}" /> 
         </Trigger> 
        </ControlTemplate.Triggers> 

       </ControlTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</ResourceDictionary> 

Window1.xaml

<Window x:Class="WpfLeakRepro.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="449" Width="497"> 
    <Grid> 
     <ListView Margin="12" 
        Name="listView" 
        ItemsSource="{Binding}"> 
      <ListView.View> 
       <GridView> 
        <GridView.Columns> 
         <GridViewColumn Header="File Name"> 
          <GridViewColumn.CellTemplate> 
           <DataTemplate> 
            <TextBlock Text="{Binding Name}" /> 
           </DataTemplate> 
          </GridViewColumn.CellTemplate> 
         </GridViewColumn> 
         <GridViewColumn Header="Thumbnail"> 
          <GridViewColumn.CellTemplate> 
           <DataTemplate> 
            <Border Background="{DynamicResource CheckeredBackground}" Width="72" Height=48/> 
           </DataTemplate> 
          </GridViewColumn.CellTemplate> 
         </GridViewColumn> 
        </GridView.Columns> 
       </GridView> 
      </ListView.View> 
     </ListView> 
    </Grid> 
</Window> 

Window1.xaml.cs

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Data; 
using System.Windows.Documents; 
using System.Windows.Input; 
using System.Windows.Media; 
using System.Windows.Media.Imaging; 
using System.Windows.Navigation; 
using System.Windows.Shapes; 
using System.ComponentModel; 
using System.Collections.ObjectModel; 
using System.IO; 

namespace WpfLeakRepro 
{ 
    public class Picture 
    { 
     public string Name { get; set; } 
    } 

    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 

      List<Picture> pictures = new List<Picture>(); 

      string[] images = new string[] {"Blue hills.jpg", "Sunset.jpg", "Water lilies.jpg", "Winter.jpg" }; 

      foreach (string imagePath in images) 
      { 
       pictures.Add(new Picture() { Name = imagePath }); 
      } 

      DataContext = pictures; 
     } 
    } 
} 

risposta

1

Il problema sembra avere qualcosa a che fare con lo VisualBrush utilizzato per lo sfondo a scacchi. Sostituirlo con un SolidColorBrush e il problema scompare. Ma non importa: la gente di Microsoft ha suggerito di installare gli ultimi aggiornamenti a .NetFx 3.5sp1, e questo sembra risolvere il problema (maggiori dettagli here).

6

Si potrebbe avere creato un problema di memoria noto in Associazioni WPF che potrebbero verificarsi durante l'associazione di proprietà delle classi non che implementa INotifyPropertyChanged. Nel tuo caso la proprietà Name della classe Picture.

Le soluzioni impostano la modalità di binding su OneTime, consentendo a Picture di implementare INotifyPropertyChanged o di effettuare Name in una proprietà di dipendenza.

Maggiori informazioni a riguardo dallo ms support e this blog post. Queste e altre note perdite di memoria WPF possono essere trovate here.

+0

Non penso che questo sia il problema. 'Picture' utilizzato per implementare' INotifyPropertyChanged', ma l'ho rimosso per abbreviare la mia app di repro.Inoltre, se questo fosse il problema, credo che la perdita sarebbe gestita - il sistema di associazione dei dati manterrebbe riferimenti agli oggetti gestiti che non dovrebbe. L'elenco delle perdite di WPF è buono (e consiglio a tutti di verificarlo), ma ho esaminato tale elenco, e penso che sia valido solo il n. 2 e questo è il problema che hai menzionato, che non sembra essere il problema Qui. Onestamente penso che questo problema sia nuovo. –

Problemi correlati