C# 线程间的线程通信

C# 线程间的线程通信,c#,.net,naudio,multithreading,C#,.net,Naudio,Multithreading,所以我有一个参数化的线程开始,初始化一些NAudio的东西。。。但是我需要一个单独的线程,告诉NAudio线程开始。当我尝试它时,它崩溃了。如何实现安全的跨线程通信 以下是线程(该类成为主线程中的音频对象): 我需要能够让我的主线程调用audio.OutDevice.Play();但我不能,因为它是跨线程的,并且崩溃了。我该怎么做呢?您的音频播放使用的是硬件资源,通常,这些资源必须在创建它们的同一线程上访问。在代码中,您没有留下继续访问线程的空间。我很惊讶您听到了这些代码,因为您拥有的线程很快就

所以我有一个参数化的线程开始,初始化一些NAudio的东西。。。但是我需要一个单独的线程,告诉NAudio线程开始。当我尝试它时,它崩溃了。如何实现安全的跨线程通信

以下是线程(该类成为主线程中的音频对象):


我需要能够让我的主线程调用audio.OutDevice.Play();但我不能,因为它是跨线程的,并且崩溃了。我该怎么做呢?

您的音频播放使用的是硬件资源,通常,这些资源必须在创建它们的同一线程上访问。在代码中,您没有留下继续访问线程的空间。我很惊讶您听到了这些代码,因为您拥有的线程很快就会超出范围。只有当这些变量与类绑定时,才会发生任何事情。我个人认为在这个场景中不需要单独的线程,因为我相信回放是或可以是非阻塞的。尽管如此,您仍可以按照计划使用以下内容(伪代码):


如果希望在后台线程上填充音频缓冲区,我建议使用WaveOutEvent类。这将创建自己的背景线程,用于通过管道拉音频。然后,您可以从主线程调用Play和Stop。在这种情况下,您需要注意的主要线程问题是,如果您需要在正在播放的文件中实现重新定位,因为重新定位将发生在GUI线程上,而另一个线程上可能正在进行读取


对于WinForms/WPF应用程序,最可靠的机制是使用WaveOut的windows消息回调(如果在GUI线程上创建WaveOut,则默认情况下会得到此消息)。这样就不必担心要在哪个线程上重新定位。此外,通过使用GUI线程进行所有操作,它避免了潜在的MTA与STA线程问题,如果您使用基于COM的API(如Windows Media API、MediaFoundation或DirectX Media Object resampler),则会出现这种问题。

我不知道此SDK,但如果您从Windows窗体控件中收到此错误,我想说你需要调用控件上的Invoke方法。你能更好地解释“it crash”吗,也许可以用一个示例异常?它崩溃是因为两个线程共享同一个资源,这会导致访问冲突。完全异常到底是什么。包括
ex.ToString()
的输出。这没有什么意义,线程不会创建硬件资源。要进一步了解GUI框架不允许跨线程访问的原因以及STA和MTA线程之间的区别,请在web上搜索相关信息。我之所以必须使用单独的线程,是因为它来自OpenTK/OpenGL应用程序,如果音频在同一个线程上,我就听不到声音,因为计算机一直在渲染图形。OpenTK中包含的OpenAL是绝对没有价值的,所以我还必须使用NAudio。同样在这里,你只是说我应该让线程2检查bool,然后线程1在需要时将bool设置为一个值,这就是它们通信的方式?那不是仍然共享bool变量吗?“线程2检查bool,然后线程1设置bool”--是的,这就是我要说的。您的跨线程异常与跨线程共享变量无关。抛出该异常是为了确保在某个线程上调用某个方法。我建议您阅读一些关于多线程应用程序的文章。头一本Java书对此有很好的解释。我认为头一本C#书也有很好的信息。这听起来是个好主意,没有捷径!请解释一下如何使用WaveOutEvent,或者给我一个指向文档的指针好吗?谢谢WaveOutEvent实现IWaveOut,您使用它与WaveOut完全相同。调用Init,然后Play.IWaveOut现在似乎是IWavePlayer
class Audio
{
    public IWavePlayer OutDevice;
    public WaveStream OutStream;

    public Thread thread;

    public Audio(string file)
    {
        this.thread = new Thread(new ParameterizedThreadStart(InitAudio)); thread.Start(file);
    }

    private void InitAudio(object data) {

        this.OutDevice = new WaveOut();
        this.OutStream = new WaveChannel32(new Mp3FileReader(data.ToString()));
        this.OutDevice.Init(OutStream);
    }
}
public bool ShouldPlay;
private void InitAudio(object data) {

        var OutDevice = new WaveOut();
        var OutStream = new WaveChannel32(new Mp3FileReader(data.ToString()));
        var OutDevice.Init(OutStream);

        while(!_exitEvent.WaitOne(50ms)){
                 if(ShouldPlay && !OutDevice.IsPlaying)
                        OutDevice.Play();
                 else if(!ShouldPlay && OutDevice.IsPlaying)
                        OutDevice.Stop();
            }
          OutDevice.Stop();
          OutDevice.Dispose();
          OutStream.Dispose();
    }