1

我对这段代码有疑问。该函数正在播放音乐曲目,因此需要一段时间才能完成执行......但是,即使它是线程化的,它也不会在完成之前返回,从而阻碍了程序的其余部分。我可以让函数退出,以便程序继续,但让音乐保持在它自己的线程上。欢迎任何解决方案。

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

谢谢您的帮助。如果您有任何想法,请发表。

4

2 回答 2

4

playWav在与 UI 运行的同一线程上执行。这就是您的 UI 被阻止的原因。

您可以像这样开始一个新线程:

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

编辑

应要求,我添加了退出线程的代码。

于 2013-05-11T20:10:53.340 回答
0

DirectSoundOut已经创建了自己的播放线程。Thread.Sleep完全摆脱阻塞线程并简单地调用Play. 订阅PlaybackStopped事件以检测播放何时完成。audioOutput需要成为班级成员,以便在播放完成后您可以使用Dispose它。

于 2013-05-12T14:31:48.447 回答