2016-04-17 2 views
1

У меня есть приложение C# WinForms, которое использует NAudio для воспроизведения звука.Исключение перекрестного вызова NAudio при завершении воспроизведения аудио

Вот код для кнопки воспроизведения:

private void btnPlayQuestionAudio_Click(object sender, EventArgs e) 
    { 
     if (btnPlayQuestionAudio.Text == "?") 
     { 
      try 
      { 
       LoadQuestionAudio(lstQuestions[glbintIndex].strQuestionAudio); 
       QuestionAudioPlayer.Play(); 
       btnPlayQuestionAudio.Text = "?"; 
       QuestionAudioPlayer.PlaybackStopped += QuestionAudioPlayer_PlaybackStopped; 
      } 
      catch (FormatException fe) 
      { 
       QuestionAudioPlayer.Stop(); 
       btnPlayQuestionAudio.Text = "?"; 
       MessageBox.Show(fe.ToString(), "oops.", MessageBoxButtons.OK, MessageBoxIcon.Error); 
      } 
     } 
     else if (btnPlayQuestionAudio.Text == "?") 
     { 
      QuestionAudioPlayer.Stop(); 
      btnPlayQuestionAudio.Text = "?"; 
     } 
    } 

А вот код для остановленного воспроизведения:

private void QuestionAudioPlayer_PlaybackStopped(Object Sender, EventArgs e) 
    { 
     btnPlayQuestionAudio.Text = "?"; 
    } 

Проблемы: Когда звук воспроизводится через полностью и «QuestionAudioPlayer_PlaybackStopped» обработчики событий выполняются , приложение вылетает в обработчике событий «QuestionAudioPlayer_PlaybackStopped» со следующим исключением:

«Необработанное исключение В System.Windows.Forms.dll произошла ошибка «System.InvalidOperationException». Дополнительная информация: Неверная операция поперечного потока: Control 'btnPlayQuestionAudio' доступен из потока, отличного от потока, на котором он был создан. "

Это не всегда происходило. Я не вижу, где находится этот новый поток Я попытался поместить весь код воспроизведения в фона рабочего, но это оказалось больше проблем, чем это стоит. Я использую только фоновые работники, когда мне нужно что-то делать, для чего потребуется больше, чем поток пользовательского интерфейса может работать безопасно и без как можно предотвратить выполнение кода в новом потоке? Или есть другой способ справиться с этим, кроме фонового работника?

ответ

0

Ваш метод «QuestionAudioPlayer_PlaybackStopped» вызывается в другом контексте потока. Вам нужно будет сделать «InvokeR equired "проверка внутри внутри, так:

private void QuestionAudioPlayer_PlaybackStopped(object sender, EventArgs e) 
{ 
    if(this.InvokeRequired) 
    { 
     // We're in an asynchronous context... 
     MethodInvoker del = delegate 
      { 
       this.QuestionAudioPlayer_PlaybackStopped(sender, e); 
      }; 
     this.Invoke(del); 
     return; 
    } 

    // This will be executed in the synchronous context: 
    btnPlayQuestionAudio.Text = "?"; 
}