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

WPF视频加载动画性能优化问题求助

WPF视频加载动画性能优化问题

我在WPF中使用视频作为加载动画,通过MediaPlayer结合Behavior实现视图Visibility设为Collapsed时启停视频,但该方案对性能影响较大,仅停止视频无法改善性能。我不想用Storyboard实现加载动画(动画效果更复杂,需要保留视频动画),转成GIF这类降低帧率的方案也不适用(要保留视频的流畅度)。尝试过使用MediaElement实现类似功能,在视图Collapsed时停止并关闭MediaElement,问题依旧,求解决方案。

XAML代码

<Border x:Name="LoadingScreenBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
    <i:Interaction.Behaviors>
        <b:MediaPlayerBehavior VideoSource="resources\animation\loadinganimationroundwhite.wmv" PlaceholderImage="Resources\Animation\PlaceholderImage\LoadingAnimationRoundWhitePlaceholder.png"></b:MediaPlayerBehavior>
    </i:Interaction.Behaviors>
</Border>

C#代码

private void OnParentIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (sender is FrameworkElement parentElement)
    {
        Console.WriteLine($"Parent visibility changed to: {parentElement.Visibility}");
        if (parentElement.Visibility == Visibility.Collapsed)
        {
            Console.WriteLine("Calling StopLoadingScreen from parent visibility change");
            StopLoadingScreen();
        }
        else if(parentElement.Visibility == Visibility.Visible && parentElement.IsLoaded == true)
        {
            Console.WriteLine("Calling StartLoadingScreen from parent visibility change");
            StartLoadingScreen();
        }
    }
}

private void StartLoadingScreen()
{
    if (VideoSource != null)
    {
        _mediaPlayer.Open(VideoSource);
    }
}

private void StopLoadingScreen()
{
    _mediaPlayer.Stop();
    _mediaPlayer.Close();
    if (_placeholderBrush != null)
    {
        AssociatedObject.Background = _placeholderBrush;
    }
    else
    {
        AssociatedObject.Background = new System.Windows.Media.SolidColorBrush(System.Windows.Media.Colors.Transparent);
    }
}

解决方案

1. 彻底释放MediaPlayer资源

仅调用Stop()和Close()不足以完全释放底层解码资源,需手动释放并置空引用,重启时重新实例化:

private void StopLoadingScreen()
{
    _mediaPlayer?.Stop();
    _mediaPlayer?.Close();
    // 释放资源并置空,断开所有引用
    _mediaPlayer?.Dispose();
    _mediaPlayer = null;
    // 设置占位背景
    AssociatedObject.Background = _placeholderBrush ?? new SolidColorBrush(Colors.Transparent);
}

private void StartLoadingScreen()
{
    if (VideoSource == null) return;
    // 重新实例化MediaPlayer
    _mediaPlayer = new MediaPlayer();
    // 设置循环播放(如果需要)
    _mediaPlayer.MediaEnded += (s, e) => _mediaPlayer.Position = TimeSpan.Zero;
    _mediaPlayer.Open(VideoSource);
    // 重新绑定视频到Background(如果之前用DrawingVisual渲染)
    var drawingVisual = new DrawingVisual();
    using (var dc = drawingVisual.RenderOpen())
    {
        dc.DrawVideo(_mediaPlayer, new Rect(AssociatedObject.RenderSize));
    }
    AssociatedObject.Background = new DrawingBrush(drawingVisual);
}

2. 卸载Behavior或清空Border内容

当视图Collapsed时,彻底断开视频渲染链路,移除Behavior或清空Border的内容:

private void OnParentIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    if (sender is FrameworkElement parentElement)
    {
        if (parentElement.Visibility == Visibility.Collapsed)
        {
            StopLoadingScreen();
            // 移除Behavior,彻底切断资源关联
            Interaction.GetBehaviors(LoadingScreenBorder).Clear();
            // 或者直接清空Border内容
            LoadingScreenBorder.Child = null;
        }
        else if (parentElement.Visibility == Visibility.Visible && parentElement.IsLoaded)
        {
            // 重新添加Behavior(如果已移除)
            if (!Interaction.GetBehaviors(LoadingScreenBorder).Any(b => b is MediaPlayerBehavior))
            {
                var behavior = new MediaPlayerBehavior
                {
                    VideoSource = new Uri("resources\\animation\\loadinganimationroundwhite.wmv", UriKind.Relative),
                    PlaceholderImage = "Resources\\Animation\\PlaceholderImage\\LoadingAnimationRoundWhitePlaceholder.png"
                };
                Interaction.GetBehaviors(LoadingScreenBorder).Add(behavior);
            }
            StartLoadingScreen();
        }
    }
}

3. 优化视频格式与硬件加速

  • 更换视频格式:WMV解码效率低,换成H.264编码的MP4格式,能显著降低CPU占用,同时保留流畅度。
  • 开启硬件加速:在App.xaml中配置强制硬件加速(默认通常开启,但可显式设置):
<Application x:Class="YourApp.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <RenderOptions>
            <RenderOptions.ProcessRenderMode>HardwareAccelerated</RenderOptions.ProcessRenderMode>
        </RenderOptions>
    </Application.Resources>
</Application>

4. 延迟加载视频

初始状态下仅显示占位图,直到视图即将变为Visible时才异步初始化MediaPlayer,避免提前占用资源:

  • 初始时Border的Background设为占位图,不加载视频
  • 监听Visibility变化,在变为Visible前异步创建MediaPlayer并开始播放
  • Collapsed时立即释放所有视频资源

内容的提问来源于stack exchange,提问作者Typisch Bär

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:27:13