前言:
WPF开发中,需要用到播放某个语音文件的情况。今天实现了MediaPlayer的封装(实现了循环播放、WPF的线程安全),在这做个记录方便查找

实现

1、添加一个MediaPlayerHelper类。提供播放,暂停、停止、循环播放功能

public class MediaPlayerHelper
{
    private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
    private static int _inTimer = 0;
    private MediaPlayer mediaPlayer = new MediaPlayer();
    private Dispatcher dispatcher;
    private bool isLooping = false;

    public event EventHandler MediaEnded;

    public MediaPlayerHelper()
    {
        mediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
        mediaPlayer.MediaFailed += MediaPlayer_MediaFailed;
    }

    private void MediaPlayer_MediaFailed(object sender, ExceptionEventArgs e)
    {
        _logger.Error(e.ErrorException.Message);
        _logger.Error(e.ErrorException.StackTrace);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="uiDispatcher">UI线程的Dispatcher</param>
    public MediaPlayerHelper(Dispatcher uiDispatcher = null) : this()
    {
        dispatcher = uiDispatcher;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="fileName">音频文件名,带扩展名</param>
    /// <param name="loop">是否循环</param>
    /// <exception cref="ArgumentException"></exception>
    private void MediaPlay(string fileName, bool loop = false)
    {
        if (string.IsNullOrEmpty(fileName))
            throw new ArgumentException("Path cannot be null or empty.", nameof(fileName));
        try
        {
            if (Interlocked.Exchange(ref _inTimer, 1) == 0)
            {
                SetVolume(1);
                var path = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Sound", fileName);
                if (File.Exists(path))
                {
                    if (dispatcher != null)
                    {
                        dispatcher.Invoke(() =>
                        {
                            isLooping = loop;
                            mediaPlayer.Open(new Uri(path, UriKind.Absolute));
                            mediaPlayer.Play();
                        });
                    }
                    else
                    {
                        isLooping = loop;
                        mediaPlayer.Open(new Uri(path, UriKind.Absolute));
                        mediaPlayer.Play();
                    }
                }
            }
        }
        catch (Exception ex)
        {
            _logger.Error($"播放语音[{fileName}]失败,{ex.Message}");
            _logger.Error(ex.StackTrace);
        }
    }

    /// <summary>
    /// 暂停
    /// </summary>
    public void Pause()
    {
        if (dispatcher != null)
        {
            dispatcher.Invoke(() =>
            {
                if (mediaPlayer.CanPause)
                {
                    mediaPlayer.Pause();
                }
            });
        }
        else
        {
            if (mediaPlayer.CanPause)
            {
                mediaPlayer.Pause();
            }
        }
    }

    /// <summary>
    /// 停止播放
    /// </summary>
    public void Stop()
    {
        if (dispatcher != null)
        {
            dispatcher.Invoke(() =>
            {
                isLooping = false;
                mediaPlayer.Stop();
                Interlocked.Exchange(ref _inTimer, 0);
            });
        }
        else
        {
            isLooping = false;
            mediaPlayer.Stop();
            Interlocked.Exchange(ref _inTimer, 0);
        }
    }

    /// <summary>
    /// 设置音量
    /// </summary>
    /// <param name="volume"></param>
    /// <exception cref="ArgumentOutOfRangeException"></exception>
    public void SetVolume(double volume)
    {
        if (volume < 0 || volume > 1)
            throw new ArgumentOutOfRangeException(nameof(volume), "Volume must be between 0.0 and 1.0.");

        if (dispatcher != null)
        {
            dispatcher.Invoke(() =>
            {
                mediaPlayer.Volume = volume;
            });
        }
        else
        {
            mediaPlayer.Volume = volume;
        }
    }

    private void MediaPlayer_MediaEnded(object sender, EventArgs e)
    {
        if (isLooping)
        {
            if (dispatcher != null)
            {
                dispatcher.Invoke(() =>
                {
                    mediaPlayer.Position = TimeSpan.Zero;
                    //mediaPlayer.Play();
                });
            }
            else
            {
                mediaPlayer.Position = TimeSpan.Zero;
                //mediaPlayer.Play();
            }
        }
        Interlocked.Exchange(ref _inTimer, 0);
        MediaEnded?.Invoke(this, e);
    }

    /// <summary>
    /// 设置进度
    /// </summary>
    /// <param name="position"></param>
    public void Seek(TimeSpan position)
    {
        if (dispatcher != null)
        {
            dispatcher.Invoke(() =>
            {
                mediaPlayer.Position = position;
            });
        }
        else
        {
            mediaPlayer.Position = position;
        }
    }

    /// <summary>
    /// 播放
    /// </summary>
    /// <param name="fileName">音频文件名,带扩展名</param>
    /// <param name="loop">是否循环</param>
    public void Play(string fileName, bool loop = false)
    {
        MediaPlay(fileName, loop);
    }
}

2、调用实例

public partial class MainWindow : Window
{
    private static MediaPlayerHelper mediaPlayer = new MediaPlayerHelper(Application.Current.Dispatcher);
    public MainWindow()
    {
        InitializeComponent();
        this.Loaded += frm_Loaded;
        this.Unloaded += frm_Unloaded;
    }

    private void frm_Loaded(object sender, RoutedEventArgs e)
    {
        mediaPlayer.PlayOk(true);
    }

    private void frm_Unloaded(object sender, RoutedEventArgs e)
    {
        mediaPlayer.Stop();
    }
}