在 mouseUp 事件上停止 SoundPlayer

Stop SoundPlayer on mouseUp event

tl;dr 版本: 如何在 WinForms 按钮的 MouseDown 事件中开始播放声音并在同一个按钮的 MouseUp 事件中停止播放?

这里是中级 C# 开发人员,我一直在尝试编写一个简单的 Simon 克隆。

我目前无法尝试让它仅在用户单击按钮时播放彩色按钮的声音。 (我交替使用 "button" 和 "tile"。两者都是指用户将在表单上按下的彩色按钮)

我最初尝试过这个:

public partial class frmMain : Form
{
    private SoundPlayer soundPlayer;

    private void btnGreenTile_MouseDown(object sender, MouseEventArgs e)
    {
        soundPlayer = new SoundPlayer(Properties.Resources.greenTileSound)
        soundPlayer.Play();
    }

    private void btnGreenTile_MouseUp(object sender, MouseEventArgs e)
    {
        soundPlayer.Stop();
    }
}

但这并没有停止声音,因为由于 MouseDown 没有完成,MouseUp 事件没有触发(仍在播放大约 5 秒长的声音,以防有人按住按钮比简单的点击更长)。 正如 Luis Tellez 在评论中提到的,SoundPlayer 在一个新线程上播放声音...所以我不知道为什么这段代码现在不起作用。

所以我研究了多线程并尝试了这个:

public partial class frmMain : Form
{
    private Thread soundThread = new Thread(new ParameterizedThreadStart(PlaySound));

    // Create stream objects for each sound (needed to allow SoundPlayer to use Resources)
    private Stream greenTileSound = Properties.Resources.greenTilePress;
    private Stream redTileSound = Properties.Resources.redTilePress;
    private Stream yellowTileSound = Properties.Resources.yellowTilePress;
    private Stream blueTileSound = Properties.Resources.blueTilePress;

    public frmMain()
    {
        InitializeComponent();
    }

    private void btnGreenTile_MouseDown(object sender, MouseEventArgs e)
    {
        soundThread.Start(greenTileSound); 
    }

    private void btnGreenTile_MouseUp(object sender, MouseEventArgs e)
    {
        soundThread.Abort();
    }

    // Have to use object as parameter because ParamterizedThreadStart() only takes object arguments
    private static void PlaySound(object soundToPlay)
    {
        SoundPlayer soundPlayer = new SoundPlayer((Stream)soundToPlay);
        soundPlayer.Play();
    }
} 

使用上面的代码,它不会停止在 MouseUp 上播放声音,更好的是它会抛出一个带有消息 "Thread is running or terminated; it cannot restart."

的 ThreadStateException

您可能会说,我只是在尝试编写这段代码时才了解多线程。我必须使用 ParameterizedThreadStart,因为它在线程启动时调用的方法 PlaySound() 需要将参数传递给 soundPlayer,其中的资源对应于播放器按下的彩色按钮(.wav 文件)。

然后我想 也许我应该尝试使用 soundThread.Suspend() 而不是 soundThread.Abort() 但是暂停已被弃用...

任何人都可以指出正确的方向让声音在 MouseUp 上停止吗?我需要使用多线程吗?我认为我的问题归结为逻辑,但我完全陷入困境。 感谢您的所有帮助! :)

作为旁注,我有点惊讶这个问题或类似的问题还没有被问到(至少我无法通过 google 搜索或 stackExchange 找到它搜索)。

您可以在其他线程中的 play() 方法 运行 的文档中看到,您可以在它之后做一些其他事情,它应该 运行,所以第一种方法的问题是与您的想法不同的东西。

The Play method plays the sound using a new thread. If you call Play before the .wav file has been loaded into memory, the .wav file will be loaded before playback starts. You can use the LoadAsync or Load method to load the .wav file to memory in advance. After a .wav file is successfully loaded from a Stream or URL, future calls to playback methods for the SoundPlayer will not need to reload the .wav file until the path for the sound changes. If the .wav file has not been specified or it fails to load, the Play method will play the default beep sound.

http://msdn.microsoft.com/en-us/library/system.media.soundplayer.play%28v=vs.110%29.aspx