You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用WPFMediaKit无故障加载播放视频,解决内存泄漏、加载失败问题

WPFMediaKit媒体播放内存泄漏与加载失败修复方案

根因定位

  • 核心问题为DirectShow非托管资源泄漏:WPFMediaKit底层封装的是DirectShow COM组件,属于非托管资源,现有释放逻辑仅调用Close()方法,没有主动销毁COM对象和视频帧缓存。你使用的5000×400分辨率视频单帧RGB缓存接近8MB,频繁加载但不彻底释放的情况下,1-2小时即可占满可用内存,后续DirectShow实例创建失败,MediaOpened事件自然无法触发。
  • WPF UI元素引用残留:你添加到ListBox的Video_playing属于UI元素,若被WPF视觉树、事件系统隐性持有引用,会导致GC无法回收托管实例,进一步阻碍非托管资源释放。
  • 异常场景未处理:偶发加载失败的视频实例没有对应的资源清理逻辑,会形成僵尸实例持续占用内存。

修复步骤

1. 完善资源释放逻辑

在原有清理逻辑基础上增加非托管资源销毁、GC强制回收步骤:

if (mediasListBoxInfo[i][1].Equals("media"))
{
    var video = (Video_playing)mediasListBox.Items[i];
    // 先暂停播放,避免资源锁导致释放失败
    video.Pause();
    // 解绑所有事件
    video.MediaOpened -= Video_MediaOpened;
    // 如果有绑定MediaFailed事件也需要解绑
    // video.MediaFailed -= Video_MediaFailed;
    video.UnloadedBehavior = WPFMediaKit.DirectShow.MediaPlayers.MediaState.Close;
    video.Close();
    // 新增:调用IDisposable接口释放DirectShow COM资源
    if (video is IDisposable disposable)
    {
        disposable.Dispose();
    }
    // 手动置空引用
    video = null;
}
mediasListBoxInfo.RemoveAt(i);
mediasListBox.Items.RemoveAt(i);
// 批量清理资源后触发一次全量GC回收,不用每次移除都调用
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

2. 优化MediaOpened事件逻辑

原有遍历ListBox的逻辑效率低且容易产生意外引用,直接转换sender即可:

private void Video_MediaOpened(object sender, System.Windows.RoutedEventArgs e)
{
    if(enablePause && sender is Video_playing video)
    {
        video.Pause();
    }
}

3. 新增加载失败异常处理

绑定MediaFailed事件,加载失败时直接清理对应实例,避免内存占用:

// 视频初始化时绑定失败事件
Video_playing video = new Video_playing(fname);
video.MediaFailed += Video_MediaFailed;

// 事件实现
private void Video_MediaFailed(object sender, System.Windows.ExceptionRoutedEventArgs e)
{
    // 此处调用你的资源清理逻辑,直接销毁加载失败的实例
}

4. 可选优化

如果轮播的视频重复率较高,可实现视频实例缓存池,无需每次都销毁重建实例,既降低DirectShow组件创建销毁的开销,也能减少资源泄漏概率。

内容的提问来源于stack exchange,提问作者V. Andris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 16:18:00