c#播放wav文件后启动秒表

时间:2013-11-24 22:32:54

标签: c# audio wav stopwatch

我正在制作秒表,我想在某种竞争中使用。我想通过点击按钮1启动我的秒表,以便播放第一个wav文件并在秒表开始之后。但秒表无法启动。这就是我到现在为止所做的。

        Stopwatch sw = new Stopwatch();

    private void button1_Click(object sender, EventArgs e)
    {
        new System.Threading.Thread(testMethod).Start();
    }

    private void testMethod(object obj)
    {
        System.Media.SoundPlayer sp = new System.Media.SoundPlayer(@"D:\...\something.wav");
        sp.Play();

    }

    void OnSoundPlayOver(object sender, EventArgs e)
    {
        timer1.Start();
        timer2.Start();
        sw.Start();

    }

1 个答案:

答案 0 :(得分:0)

如果您的要求是:

  • 播放声音的开始按钮,然后启动一个显示屏幕上已用时间的计时器。
  • 停止当前计时器的停止按钮,将最后一个值保留在屏幕上。
  • 在Windows窗体中实现。

以下代码是如何使上述要求有效的BASIC示例。它利用SoundPlayer的PlaySync方法,BackgroundWorker(将标签上的值更新为经过的秒数)和实际记录经过时间的秒表。它绝对不是实现这一目标的最佳方式,但它应该为您提供一个起点。

需要注意的一点是,您无法从与创建标签的线程(通常是UI线程)不同的线程更新Label。因此,如果您尝试从另一个线程更新标签的文本,则需要使用标签.Invoke方法(请参阅下面代码中的 ThreadSafeUpdateLabel 方法)。

此代码未考虑有人垃圾邮件点击“开始”按钮的情况(它只是单击您播放的声音次数),并且只要获取声音,当您单击“开始”按钮时,UI就会冻结玩。我将把这些问题作为代码的自然扩展来解决。

无论如何,在代码上:

private Stopwatch _timer = new Stopwatch();
private BackgroundWorker _worker;

private void btnStop_Click(object sender, EventArgs e)
{
    CancelExistingBackgroundWorker();
    _timer.Stop();
}

private void btnStart_Click(object sender, EventArgs e)
{
    CancelExistingBackgroundWorker();
    _timer.Reset();
    UpdateLabel(0);

    _worker = new BackgroundWorker() { WorkerSupportsCancellation = true };
    _worker.DoWork += (a, b) => 
    { 
        while (true) 
        {
            if ((a as BackgroundWorker).CancellationPending) return;
            ThreadSafeUpdateLabel();
            Thread.Sleep(100);
        } 
    };

    var soundPlayer = new SoundPlayer("wavfile.wav");
    soundPlayer.PlaySync();

    _timer.Start();
    _worker.RunWorkerAsync();
}


private void ThreadSafeUpdateLabel()
{
    if (lblElapsed.InvokeRequired)
    {
        lblElapsed.Invoke(new Action(() => ThreadSafeUpdateLabel()));
    }
    else
    {
        UpdateLabel(_timer.Elapsed.TotalSeconds);
    }
}

private void UpdateLabel(double seconds)
{
    lblElapsed.Text = seconds.ToString();
}

private void CancelExistingBackgroundWorker()
{
    if (_worker != null)
    {
        _worker.CancelAsync();
        _worker.Dispose();
    }
}