ListBox中的MediaElement导致内存泄漏

时间:2014-10-30 19:22:44

标签: c# wpf memory-leaks

我有一个虚拟化的ListBox,其中有大量的GIF从HDD加载,循环播放。

我正在使用Grid,因为我打算在控件中添加更多内容,所以请坚持下去。

LongFileName是一个完整路径。

public class cThumbnail3 : System.Windows.Controls.Grid
{
   public string LongFileName
    {
        get { return (string)GetValue(LongFileNameProperty); }
        set { SetValue(LongFileNameProperty, value); }
    }
    public static readonly DependencyProperty LongFileNameProperty =
        DependencyProperty.Register("LongFileName", typeof(string), typeof(cThumbnail3), new PropertyMetadata(OnLongFileNameChanged));


    static void OnLongFileNameChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
    {
        cThumbnail3 t = obj as cThumbnail3;
        t.LoadAsGif();
    }

    private MediaElement ME;
    public void LoadAsGif()
    {
        ME = new MediaElement();
        ME.UnloadedBehavior = MediaState.Manual;
        Uri uri = new Uri(@"file://" + LongFileName);
        ME.Source = uri;
        ME.MediaEnded += (o, e) =>
            {
                ME.Position = new TimeSpan(0, 0, 1);
                ME.Play();
            };
        this.Children.Clear();
        this.Children.Add(ME);
    }
}

xaml现在很简单

<local:cThumbnail3 LongFileName="{Binding FullPath}" />

我在列表框中向上和向下滚动时监视内存使用情况。每次项目进入视图时,都会创建新的cThumbnail3,并且项目从头开始播放。

问题是一段时间后内存消耗达到1.2GB并且播放停止

修改 我还尝试了什么: 当控件不在视图中时,不同地添加事件+卸载所有内容

private bool IsVisible { get; set; }

public void LoadAsGif()
{
   ME = new MediaElement();
   ME.UnloadedBehavior = MediaState.Manual;
   Uri uri = new Uri(@"file://" + LongFileName);
   ME.Source = uri;
   ME.MediaEnded += ME_MediaEnded;
}
private void ME_MediaEnded(object sender, RoutedEventArgs e)
{
  if (!IsVisible) return;
  ME.Position = new TimeSpan(0, 0, 1);
  ME.Play();
}

private PropertyChangedEventHandler propertyChanged;

public event PropertyChangedEventHandler PropertyChanged
{
    add
    {
        var wasAttached = propertyChanged != null;
        propertyChanged += value;
        var isAttached = propertyChanged != null;

        if (!wasAttached && isAttached)
            OnPropertyChangedAttached();
    }
    remove
    {
        var wasAttached = propertyChanged != null;
        propertyChanged -= value;
        var isAttached = propertyChanged != null;

        if (wasAttached && !isAttached)
        {
            OnPropertyChangedDetached();
        }
    }
}

void OnPropertyChangedAttached()
{
    IsVisible = true;
    if (ME != null)
        ME.Play();
}

void OnPropertyChangedDetached()
{
    IsVisible = false;
    if (ME != null)
    {
        ME.MediaEnded -= ME_MediaEnded;
        ME.Stop();
        ME.Close();
        ME.Source = null;
        ME = null;
    }
}

1 个答案:

答案 0 :(得分:1)

您可以尝试为MediaEnded事件编写完整的方法,并在类的析构函数中为事件编写-=。我猜这个事件是罪魁祸首,这可能导致物体无法妥善处理。

您还可以为ListBox设置VirtualizingStackPanel.IsVirtualizing="true"以提高性能。在http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.isvirtualizing(v=vs.110).aspx

上查找有关它的更多信息