WPF項目中有一個功能需要不停循環播放不同的視頻,且每個視頻的播放時間也不固定。於是用到了LIBVLC,但是在測試的過程中,卻發現有內存泄漏,於是寫了下邊的Demo,測試很久,仍然不知是何原因,請有遇到過的朋友請幫忙在下邊評論留言。
項目代碼里有以下這兩個文件的使用,可點擊下載這兩個文件,並放到項目的Resource文件夾下,並在文件屬性--復制到輸出目錄上設置“始終復制”。(因cnblogs每次上次文件限10M,所以文件和代碼分開上傳了)
項目代碼: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內存泄漏問題,謝謝了。