在播放SoundPlayer时从其他线程停止播放

时间:2019-10-22 08:25:48

标签: c#

为了制作一个(随机播放的)播放列表,我创建了一个单独的线程,在其中加载和播放播放列表中的每首歌曲。后台内容(wav文件,文件路径,播放列表和混排)都可以顺利进行。

问题是我有2个窗口,每个窗口都可以关闭和打开另一个窗口。每个窗口都有一个不同的播放列表,当我切换到另一个窗口时,我希望我的静态SoundPlayer停止播放,然后开始播放新的播放列表。

当前无法使用:目前,应用程序会等到当前曲目结束后再显示下一个窗口并启动另一个播放列表。是的,整个应用程序都在等待。

我是线程编码的新手,所以我不太确定该怎么做。到目前为止,我尝试过的两种阻止此问题的方法是SoundPlayer.Stop()和Thread.Abort()。完全没有改变情况。

在每个窗口中:

Thread playlistThread;
public Window()
{
    InitializeComponent();
    MusicPlayer.music.Stop();
    playlistThread = new Thread(() => MusicPlayer.PlayPlaylist(MusicPlayer.ShufflePlaylist(MusicPlayer.PlaylistFromType("[insert track type]"), random)));
    playlistThread.Start();
接下来将显示的

PlayPlaylist需要一个字符串列表,所以不必担心Thread行,它只是将几个部分放在一起。此后的属性仅生成该列表,然后再次生成所有列表,但是如果有人认为有必要,我可以显示它。这是PlayPlaylist方法:

public static void PlayPlaylist(List<string> tracks)
{
    for (int i = 0; i < tracks.Count; i++)
    {
        music.SoundLocation = tracks[i];
        music.PlaySync();
    }
}

1 个答案:

答案 0 :(得分:0)

这是我得出的答案:

public static void PlayTrack(List<string> tracks, int i)
{
    while (true)
    {
        if (i == tracks.Count)
        {
            tracks = MusicPlayer.ShufflePlaylist(tracks, MusicPlayer.random);
            i = 0;
        }
        music.SoundLocation = tracks[i];
        int l = SoundInfo.GetSoundLength(tracks[i]);
        music.Play();
        while (l > 0)
        {
            Thread.Sleep(1000);
            l -= 1000;
        }
        i++;
    }
}

我发现here的SoundInfo类及其GetSoundLength方法。 该方法起作用而其他方法不起作用的原因是因为Play()和PlaySync()的工作方式。 PlaySync()会在当前线程中播放整个.wav文件,直到完成后,其他任何文件都不会运行。因此,即使SoundPlayer.Stop()和Thread.Abort()也不起作用,因为它们在当前行之后插入新行。

通过在新线程中运行此方法,可以避免PlaySync()出现此问题。但是,仍然不可能使用PlaySync()提前停止曲目。这就是为什么您改用Play()的原因。

但是,这里存在第二个问题:Play()在其自己的线程中播放曲目,这意味着其余代码将继续。如果您只想在当前曲目完成后 之后做任何事情,这是一个很大的风险。

答案是计算要播放的曲目的长度。然后,简单地创建一个while循环,一直运行到l(由GetSoundLength()给出)达到0为止。在每次循环中,线程(与窗口的主线程分开)都休眠1秒钟。在CPU上这样做很好,这意味着可以将第二个额外的代码(例如SoundPlayer.Stop())注入线程中。