在 c# 中线程化函数不起作用

Posted

技术标签:

【中文标题】在 c# 中线程化函数不起作用【英文标题】:Threading a Function in c# is not Working 【发布时间】:2013-05-11 20:07:20 【问题描述】:

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

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

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

【问题讨论】:

【参考方案1】:

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

编辑

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

【讨论】:

非常感谢,这解释了线程如何更好地工作! 事后如何停止 Tread?现在我无法杀死它,因为线程在静态函数中。 函数是否为静态无关紧要。您应该将线程视为在“主进程”旁边运行的单独“进程”。它们并排运行并执行各种代码(静态、非静态、创建实例等)。停止线程的最好方法是设置一个标志。我会更新我的答案。 感谢您的帮助,这对暂停音乐很有用,但是您如何杀死线程?我不能导致退出。如果我设置线程,我可以让它退出,但即使那样我也无法在程序中杀死它【参考方案2】:

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

【讨论】:

你能给我举个例子吗,我明白你在说什么,但不知道如何在我自己的代码中实现它。

以上是关于在 c# 中线程化函数不起作用的主要内容,如果未能解决你的问题,请参考以下文章

C# 调用 ListView 不起作用(后台线程)

使用由`fork`创建的多个C线程的回调函数时,Rust Mutex不起作用

linux 平台上 C# 中的自定义 posix 信号不起作用

C# 创建 websocket - onmessage 函数不起作用

即使我在 .cpp 文件中实例化一个虚拟对象,在 .cpp 文件中定义模板函数也不起作用

C# Split() 函数不起作用