joshua-anderson
joshua-anderson

Reputation: 4466

Threading a Function in c# is not Working

I have a problem with this code. The function is playing a music track, so it takes a while to finish executing.... However, even through it is threaded, it does not return untill it is done, holding up the rest of the program. Can I have the function exit so that the program continues but have the music keep on it's own thread. Any solutions are welcome.

using System;
using Gtk;
using NAudio;
using NAudio.Wave;
using System.Threading;

public class Trackbox {

    public static void Main() {
        Application.Init();

        //Create the Window
        Window myWin = new Window("Trackbox");
        myWin.SetIconFromFile("Assets//logo.png");
        myWin.Resize(200, 100);


        //Add the label to the form     
        //myWin.Add(myLabel);

        Button playButton = new Button("Play Sound");
        //This when playwav is called here, the rest of the application waits for it to finish playing

        playButton.Clicked += new EventHandler(playWav);
        myWin.Add(playButton);

        myWin.DeleteEvent += delegate { Application.Quit(); };
        //Show Everything     
        myWin.ShowAll();


        Application.Run();


    }

    private static void playWav(object sender, EventArgs e)
    {
        var soundFile = @"C:\sound.wav";
        using (var wfr = new WaveFileReader(soundFile))
        using (WaveChannel32 wc = new WaveChannel32(wfr) { PadWithZeroes = false })
        using (var audioOutput = new DirectSoundOut())
        {
            audioOutput.Init(wc);

            audioOutput.Play();

            while (audioOutput.PlaybackState != PlaybackState.Stopped)
            {
                Thread.Sleep(20);
            }

            audioOutput.Stop();
        }
    }
}

Thanks for the help. If you have any ideas please post.

Upvotes: 1

Views: 1002

Answers (2)

Mark Heath
Mark Heath

Reputation: 49492

DirectSoundOut already creates its own playback thread. Get rid of the Thread.Sleep altogether which is blocking your thread and simply call Play. Subscribe to the PlaybackStopped event to detect when playback has finished. The audioOutput would need to be a class member so you could Dispose it after playback had finished.

Upvotes: 0

Martin Mulder
Martin Mulder

Reputation: 12954

Your playWav is executed on the same thread as your UI is running on. That is why your UI is blocked.

You can start a new thread like this:

private volatile bool _QuitThread;

private void playWav(object sender, EventArgs e)
{
    _QuitThread = false;
    Thread thread = new Thread(playWavThread);
    thread.Start();
}

// This method should be called when the music should stop. Perhapse when a button has been pressed.
private void StopTheMusic() 
{
    _QuitThread = true;
}

private void playWavThread()
{
    var soundFile = @"C:\sound.wav";
    using (var wfr = new WaveFileReader(soundFile))
    using (WaveChannel32 wc = new WaveChannel32(wfr) { PadWithZeroes = false })
    using (var audioOutput = new DirectSoundOut())
    {
        audioOutput.Init(wc);
        audioOutput.Play();
        while (!_QuitThread && audioOutput.PlaybackState != PlaybackState.Stopped)
        {
            Thread.Sleep(20);
        }
        audioOutput.Stop();
    }
}

EDIT

At request, I added code to quit the thread.

Upvotes: 4

Related Questions