В качестве побочного проекта я реализую матрицу MIDI для соединения нескольких клавиатур MIDI с источниками звука. Ключевым требованием здесь является эхо MIDI-данных, полученных на входном порте, на выбранный выходной порт.
Создав необходимые объявления и оболочки P / Invoke, я заметил, что документация Win32 MIDI для MidiInProc
гласит: «Приложения не должны вызывать какие-либо мультимедийные функции изнутри функции обратного вызова, поскольку это может вызвать тупик» .
Учитывая, что небезопасно вызывать midiOutShortMsg
из MidiInProc
, мое текущее решение - записать MIDI-данные в очередь и установить событие. Рабочий поток ожидает события и вызывает midiOutShortMsg
. Общая идея такова: -
static void InputCallback( int hMidiIn, uint wMsg, uint dwInstance, uint dwParam1, uint dwParam2 )
{
if( wMsg == MM_MIM_DATA )
{
data.EnQueue( dwParam1 ); //data is a Queue<uint>
dataReady.Set(); //dataReady is AutoResetEvent
}
}
void ThreadProc
{
while( !_done )
{
dataReady.WaitOne();
midiOutShortMsg( hMidiOut, data.DeQueue() );
}
}
Однако, хотя в тестировании это работало нормально, между вызовами dataReady.Set()
и InputCallBack
, по-видимому, существует окно возможности возврата, во время которого выгрузка может позволить рабочему потоку вызвать midiOutShortMsg
(хотя и в другая тема).
Этот подход безопасен?