使用 SoundPlayer 在音乐结束后做一些事情

Do something after a music ends with SoundPlayer

我需要在我的异步加载音乐文件完成后做一些事情。比方说我想让程序退出什么的。现在我该怎么做才能在音乐结束后完成?

    private void button1_Click(object sender, EventArgs e)
    {
        player.SoundLocation = @"Music\" + FileList[0];
        player.LoadAsync();
    }

    private void Player_LoadCompleted(object sender, AsyncCompletedEventArgs e)
    {
        if (player.IsLoadCompleted)
        {
            player.PlaySync();
        }
    }

由于 PlaySync 方法是同步的,因此它不会 return 直到文件播放完毕。所以,你可以简单地这样做:

if (player.IsLoadCompleted)
{
    player.PlaySync();
    DoSomethingAfterMusicIsDone();
}

更新:

如果 SoundLocation 指向文件系统上的文件,

LoadAsync 似乎会 运行 同步。这意味着如果您不想冻结 UI 线程,您应该在另一个线程上调用 LoadAsync。这是一个例子:

Task.Run(() => player.LoadAsync());

改为使用 MediaPlayer:

mediaPlayer = new MediaPlayer();
mediaPlayer.MediaEnded += delegate { MessageBox.Show("Media Ended"); };
mediaPlayer.Open(new Uri(@"C:\myfile.mp3"));
mediaPlayer.Play();

理论上听起来不错。但是,实际上,我无法触发 MediaEnded 事件。因此,我不得不按如下方式轮询 MediaEvent 的结束:

while(true)
{
    System.Threading.Thread.Sleep(1000);
    string pos = "unknown";
    string dur = "unknown";

    try 
    {
        pos = mediaplayer1.Position.Ticks.ToString();
        dur = mediaplayer1.NaturalDurataion.TimeSpan.Ticks.ToString()
        if (pos == dur)
        {
            // MediaEnded!!!!!
            pos = "0";
            dur = "0";
        }
        catch {}
    }
}

从积极的方面来说,您可以通过轮询更新您的音频播放器滑块... 不利的一面是,如果您注意到 1000 毫秒的延迟,它会使暂停按钮有点反应迟钝...

如果您使用此解决方法,我建议将 Mediaplayer 放在后台线程中,这样轮询循环就不会锁定 UI 线程。