WPF VLC 循环新增和删除播放器会产生内存泄漏(WPF VLC Memory Leak)

 WPF项目中有一个功能需要不停循环播放不同的视频,且每个视频的播放时间也不固定。于是用到了LIBVLC,但是在测试的过程中,却发现有内存泄漏,于是写了下边的Demo,测试很久,仍然不知是何原因,请有遇到过的朋友请帮忙在下边评论留言。

 

 

项目代码里有以下这两个文件的使用,可点击下载这两个文件,并放到项目的Resource文件夹下,并在文件属性--复制到输出目录上设置“始终复制”。(因cnblogs每次上次文件限10M,所以文件和代码分开上传了)

2019100916.flv

20190906020.flv

项目代码:WpfVlcApp

 

运行效果如下:

 

项目下载后需要发布,随便选一个地方发布即可。

 

 

 设置数据收集器,可通过https://www.cnblogs.com/suterfo/p/12329711.html 的方法来设置数据收集器,运行1小时,监控内存泄漏。以下是我用数据收集器收集到的内存泄漏情况,通常要测试半天或以上才能准确反应出有内存泄漏。

 

 

 

  

不想下载测试的朋友可看以下主要的代码:

 public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();


            Init();
        }
        VlcVideoControl vlcVideoControl_1 = null;
        VlcVideoControl vlcVideoControl_2 = null;
        bool isSingular = true;

        private void Init()
        {
            Thread thread = new Thread(VideoThread);
            thread.IsBackground = true;
            thread.Start();

        }

        private void VideoThread()
        {
            while (true)
            {
                AddOrDelVideo();
                if (vlcVideoControl_1 != null)
                {
                    Thread.Sleep(5 * 1000);
                }
            }
        }


        private void AddOrDelVideo()
        {
            string mediaPth = Directory.GetCurrentDirectory();
            cav_container.Dispatcher.Invoke(() =>
            {
                try
                {
                    if (vlcVideoControl_1 == null)
                    {
                        //Trace.WriteLine("--------------------------------------------");
                        string strMedia1 = System.IO.Path.Combine(mediaPth, "Resource", "2019100916.flv");

                        vlcVideoControl_1 = new VlcVideoControl();
                        vlcVideoControl_1.SourcePath = strMedia1;
                        vlcVideoControl_1.SetPosition(0);
                        vlcVideoControl_1.Width = 300;
                        vlcVideoControl_1.Height = 200;
                        cav_container.Children.Add(vlcVideoControl_1);
                        Canvas.SetTop(vlcVideoControl_1, 0);
                        Canvas.SetLeft(vlcVideoControl_1, 0);

                        if (!isSingular && (vlcVideoControl_2 == null))
                        {
                            string strMedia2 = System.IO.Path.Combine(mediaPth, "Resource", "20190906020.flv");
                            vlcVideoControl_2 = new VlcVideoControl();
                            vlcVideoControl_2.SourcePath = strMedia2;
                            vlcVideoControl_2.SetPosition(0);
                            vlcVideoControl_2.Width = 300;
                            vlcVideoControl_2.Height = 200;
                            cav_container.Children.Add(vlcVideoControl_2);
                            Canvas.SetTop(vlcVideoControl_2, 0);
                            Canvas.SetLeft(vlcVideoControl_2, 310);
                        }
                        isSingular = !isSingular;
                    }
                    else
                    {
                        vlcVideoControl_1.Stop();
                        cav_container.Children.Remove(vlcVideoControl_1);
                        vlcVideoControl_1 = null;

                        if (vlcVideoControl_2 != null)
                        {
                            vlcVideoControl_2.Stop();
                            cav_container.Children.Remove(vlcVideoControl_2);
                            vlcVideoControl_2 = null;
                        }
                        //GC.Collect();
                    }
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex);
                }
            });

        }

    }

 

using LibVLCSharp.Shared;
using LibVLCSharp.WPF;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows;

namespace WpfVlcApp
{
    public class VlcVideoControl : VideoView
    {

        #region 枚举和常数

        #endregion

        #region 成员变量
        private static LibVLC m_LibVlc;
        private Media m_media;
        #endregion

        #region 构造函数
        /// <summary>
        /// 静态构造函数只执行一次
        /// </summary>
        static VlcVideoControl()
        {
            Core.Initialize();
            m_LibVlc = new LibVLC();
        }

        public VlcVideoControl()
        {
            m_media = null;
            MediaPlayer = new LibVLCSharp.Shared.MediaPlayer(m_LibVlc);
            MediaPlayer.EndReached += MediaPlayer_EndReached;
            Loaded += ControlLoaded;
        }
     
        #endregion

        #region 属性
        public string SourcePath { get; set; }
        #endregion

        #region 事件
        private void ControlLoaded(object sender, RoutedEventArgs e)
        {
            string aspect = $"{(int)ActualWidth}:{(int)ActualHeight}";
            MediaPlayer.AspectRatio = aspect;
            if (File.Exists(SourcePath))
            {
                m_media = new Media(m_LibVlc, SourcePath, FromType.FromPath);
                MediaPlayer.Play(m_media);
            }
        }
        private void MediaPlayer_EndReached(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(_ => this.MediaPlayer.Play(m_media));
        }
        #endregion

        #region Public 方法
        public void SetPosition(long position)
        {
            if (position > 0)
            {
                MediaPlayer.Time = position;
            }
        }

        public void Stop()
        {
            this.Dispatcher.Invoke(() =>
            {
                Loaded -= ControlLoaded;
              
                this.Dispose();

                m_media?.Dispose();
                m_media = null;

                if (MediaPlayer != null)
                {
                    MediaPlayer.EndReached -= MediaPlayer_EndReached;
                    MediaPlayer.Stop();

                    if (MediaPlayer.Media != null)
                    {
                        MediaPlayer.Media.Dispose();
                        MediaPlayer.Media = null;
                    }

                    MediaPlayer.Dispose();
                }
            });
        }
        #endregion

        #region Private 方法

        #endregion

    }

}

 

有遇到过的朋友,请帮忙指定上边代码的WPF VLC内存泄漏问题,谢谢了。

 

posted @ 2020-09-12 09:52  努力吧兄Dei  阅读(1698)  评论(9编辑  收藏  举报