在mouseUp事件上停止SoundPlayer

时间:2015-01-04 08:52:10

标签: c# multithreading 2d-games soundplayer

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

中级C#dev在这里,我一直试图编写一个简单的Simon克隆。

我目前只是在用户单击按钮时试图让它播放彩色按钮的声音。 (我使用"按钮"和" 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();
    }
}

但是这并没有停止声音,因为MouseUp事件由于MouseDown没有完成而没有触发(仍然播放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上播放声音,甚至更好地抛出一个带有消息的ThreadStateException"线程正在运行或终止;它无法重启。"

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

然后我想也许我应该尝试使用soundThread.Suspend()而不是soundThread.Abort()但不推荐使用Suspend ......

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

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

1 个答案:

答案 0 :(得分:1)

你可以在文档中看到play()方法在其他线程中运行,你可以在它之后执行其他操作并且应该运行,所以第一种方法的问题与你的想法有所不同。

  

Play方法使用新线程播放声音。如果你打电话给Play   在.wav文件加载到内存之前,.wav文件将会   在播放开始前加载。您可以使用LoadAsync或Load   提前将.wav文件加载到内存的方法。在.wav文件之后   从Stream或URL成功加载,以后调用回放   SoundPlayer的方法不需要重新加载.wav文件   直到声音的路径发生变化。如果.wav文件还没有   指定或无法加载,Play方法将播放默认值   发出哔哔声。

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