user3029389
user3029389

Reputation: 3

c# Starting a stopwatch after wav file is played

I am working on a stopwatch, that i want to use in some sort of competition. I would like to start my stopwatch by clicking Button 1 in order that first wav file is played and after that stopwatch starts. But Stopwatch doesn't start. This is what I came up to till now.

        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();

    }

Upvotes: 0

Views: 404

Answers (1)

Todd Bowles
Todd Bowles

Reputation: 1574

If your requirements are:

  • Start button that plays a sound, then starts a timer that displays the elapsed time on the screen.
  • Stop button that stops any current timers, leaving the last value on the screen.
  • Implemented in Windows Forms.

The following code is a BASIC example of how to get the above requirements working. It leverages the PlaySync method of SoundPlayer, a BackgroundWorker (to update the value on the label to be the elapsed seconds) and a Stopwatch for actually recording the elapsed time. It is definitely not the BEST way to accomplish this, but it should provide a starting point for you.

An important thing to note is that you cannot update a Label from a thread that is different from the thread that created the label (typically the UI thread). So if you're trying to update the Text of a label from another thread you need to use the labels .Invoke method (see the ThreadSafeUpdateLabel method in the code below).

This code does not take into account the situation where someone spam clicks the Start button (it just plays the sound as many times as you click) and the UI freezes when you click the Start button for as long as it takes the sound to play. I'll leave fixing those issues to you as a natural extension of the code.

Anyway, onto the code:

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();
    }
}

Upvotes: 1

Related Questions