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內存泄漏問題,謝謝了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM