作为一个附带项目,我正在实现一个 MIDI 矩阵,以将多个 MIDI 键盘与声源互连。这里的关键要求是将输入端口上接收到的 MIDI 数据回显到选定的输出端口。
创建了必要的 P/Invoke 声明和包装器后,我注意到 Win32 MIDI 文档的MidiInProc
状态:“应用程序不应从回调函数内部调用任何多媒体函数,因为这样做会导致死锁”。鉴于从内部
调用是不安全的,我当前的解决方案是将 MIDI 数据写入队列并设置事件。工作线程等待事件并调用. 总体思路是这样的:-midiOutShortMsg
MidiInProc
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
(尽管在另一个线程中)。
这种方法安全吗?