2013-02-28 4 views
1

Итак, у меня есть параметризованный запуск потока, который инициализирует некоторые файлы NAudio ... Но мне нужно, чтобы отдельный поток рассказывал, что нить NAudio запускается. Когда я пытаюсь, он падает. Как я могу реализовать безопасную межпоточную связь?потоковая связь между потоками

Вот нить (этот класс становится аудиообъект в основном потоке):

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

мне нужно, чтобы быть в состоянии иметь свой основной audio.OutDevice.Play поток вызова(); но я не могу, потому что это перекрестная резьба, и она падает. Как мне это сделать?

+0

Я не знаю этого SDK, но если вы получили эту ошибку из элемента управления Windows Forms, я бы сказал, что вам нужно вызвать метод Invoke для элемента управления. –

+0

Можете ли вы объяснить, «он падает» лучше, возможно, с примером исключения? –

+0

Сбой из-за двух потоков, разделяющих один и тот же ресурс, что приводит к нарушениям доступа. – sableguy00

ответ

0

Воспроизведение аудио использует аппаратные ресурсы, и, как это обычно бывает, к ним нужно обращаться в том же потоке, на котором они были созданы. В вашем коде вы не оставили места для продолжения доступа к потоку. Я удивлен, что у вас есть звук этого кода, так как ваш собственный поток вскоре выйдет за рамки. Это связано только с тем, что у вас есть переменные, привязанные к классу, что произошло. Я лично не думаю, что вам нужен отдельный поток в этом сценарии, поскольку я считаю, что воспроизведение является или может быть неблокирующим. Несмотря на это, вы могли бы следовать ваш план с чем-то вроде этого (псевдокод):

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

Это мало смысла, потоки не создают аппаратные ресурсы. –

+0

Чтобы узнать больше о поиске в Интернете для получения информации о том, почему инфраструктура графического интерфейса не разрешает сквозной доступ и какая разница между потоками STA и MTA. – Brannon

+0

Причина, по которой я должен использовать отдельный поток, заключается в том, что это происходит из приложения OpenTK/OpenGL, и если звук находится в одном потоке, я не получаю звука, потому что компьютер тратит все свое время на графику. OpenAL, входящий в OpenTK, абсолютно бесполезен, поэтому я также должен использовать NAudio. Также в этом вы просто говорите, что мне нужно, чтобы поток 2 проверял bool, а затем поток 1 задает значение bool при необходимости, вот как они общаются? Разве это еще не разделило бы переменную bool? – sableguy00

0

Если вы хотите аудио буферы должны быть заполнены на фоне потока, я рекомендую использовать класс WaveOutEvent. Это создаст собственный фоновый поток для вытягивания звука по конвейеру. Затем вы можете вызвать Play и Stop из основного потока. Основная проблема с потоками, о которой вы должны остерегаться в этой ситуации, - это если вам нужно реализовать репозиционирование в файле, который вы воспроизводите, поскольку репозиционирование будет происходить в потоке графического интерфейса, в то время как чтение потенциально выполняется на другом.

Для приложений WinForms/WPF самым надежным механизмом является использование обратных вызовов сообщений Windows WaveOut (вы получите это по умолчанию, если вы создадите WaveOut в потоке графического интерфейса). Это позволяет избежать необходимости беспокоиться о том, какой поток вы перемещаете. Кроме того, используя поток GUI для всего, он избегает возможных проблем с потоками MTA и STA, которые вы получите, если будете использовать API на основе COM, такие как Windows Media API, MediaFoundation или ремаркетинг объекта DirectX Media.

+0

Это звучит неплохо, без ярлыков! Можете ли вы объяснить, как использовать WaveOutEvent, или дать мне указатель на документацию? Благодаря! – sableguy00

+0

WaveOutEvent реализует IWaveOut, и вы используете его точно так же, как WaveOut. Call Init, затем Play. –

+0

IWaveOut теперь кажется IWavePlayer –

Смежные вопросы