Потокобезопасный вызов из асинхронной операции в BackgroundWorker
У меня есть некоторый код в BackgroundWorker, который помогает мне предотвратить зависание интерфейса при подключении Bass к аудиопотоку:
Private Sub WorkerConnectToStream_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles WorkerConnectToStream.DoWork
Bass.BASS_StreamFree(StreamNumber)
StreamNumber = Bass.BASS_StreamCreateURL(StreamAddr, 0, BASSFlag.BASS_STREAM_STATUS, _downloadProc_, Me.Handle)
If StreamNumber <> 0 Then
Bass.BASS_ChannelPlay(StreamNumber, True)
End If
End Sub
Но я получаю: InvalidOperationException с сообщением: "Имя элемента управления получено из потока, отличного от потока, в котором он был создан". Если для свойства CheckForIllegalCrossThreadCalls задано значение false или я запускаю программу из папки Debug, то все в порядке, но это не лучшее решение.
если я использую:
invoke(sub()
StreamNumber = Bass.BASS_StreamCreateURL(StreamAddr, 0, BASSFlag.BASS_STREAM_STATUS, _downloadProc_, Me.Handle)
end sub)
тогда это сообщение исчезает, но интерфейс моей формы зависает. Как я могу решить эту проблему? Большое спасибо! Я извиняюсь за мой плохой английский.
1 ответ
Проблема в том, что ваш DoWork
работает в фоновом потоке, но вызывает элемент управления в основном потоке. Управление не может этого сделать. Вы должны поднять событие, такое как ReportProgress
в вашем Dowork
, передать данные и обновить свой контроль там. Это то, что BGW. Это позволяет вам взаимодействовать с элементами управления без написания тонны кода для управления потоками.
Если вы используете какой-то элемент управления для чего-то, и этот элемент управления находится в форме, вместо этого попытайтесь создать его экземпляр в потоке BG и использовать его только в памяти. Я помню, я сделал что-то подобное, и это сработало.