WPF VLC 循环新增和删除播放器会产生内存泄漏(WPF VLC Memory Leak)
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内存泄漏问题,谢谢了。