Sorry, discovered this invitation a bit late ... ;-)

Well, decoupling with Typelib-defined Calls, usually per PostMessage and then leaving the CallBack as fast as possible -
this approach was already mentioned - and that's what works and what I usually do as well (when we talk about Callbacks from different threads)...
which would be definitely the issue e.g. with the Multimedia-Timer-Callbacks ...

Not sure, if the WaveIn-callbacks fall into the same (foreign threaded) category, since I never forced those (by passing a Zero-Param)
whilst working with the WaveIn-API ... a normal polling per API-Timer (which may serve here now as an example for:
"friendly and secure callbacks on the same thread") was entirely enough.

Here's some code, not in the context of a working example, but "copied as found" from an already 13 year old Demo, which still works here.

It is using a (class-encapsulated) API-Timer - in conjunction with a RingBuffer-Array (and -Indexing).
Maybe that worth' a look from jmsrickland

Code:
Private Type Stereo
  L As Integer
  R As Integer
End Type

Private Type FFTStereo
  L As Double
  R As Double
End Type

Private Type WaveHdr
    lpData As Long
    dwBufferLength As Long
    dwBytesRecorded As Long
    dwUser As Long
    dwFlags As Long
    dwLoops As Long
    lpNext As Long 'wavehdr_tag
    reserved As Long
End Type

Private Type WavBuf
  Hdr As WaveHdr
  Arr(1023) As Stereo '23 msec (4kB ByteSize - and 43Hz at 44100)
  FFT(1023) As FFTStereo
End Type

Private RBuf(29) As WavBuf, RIdx&, xt 'As APITimerClassEncapsulation

Private Sub DoStop()
Dim i&
  xt.Enabled = False
  If DevHandle Then
    For i = 0 To UBound(RBuf)
      waveInUnprepareHeader DevHandle, RBuf(i).Hdr, Len(RBuf(i).Hdr)
    Next i
    waveInReset DevHandle
    waveInClose DevHandle
    DevHandle = 0
  End If
End Sub

Private Sub xt_Timer() '<- API-Timer-Eventsink (the normal one, not a MultiMedia-Timer)
Dim i&
  Do While RBuf(RIdx).Hdr.dwFlags And WHDR_DONE
    ProcessBuf RBuf(RIdx)
    RIdx = CIdx(RIdx + 1)
  Loop
  For i = RIdx To RIdx + UBound(RBuf)
    InitBuf RBuf(CIdx(i))
  Next i
End Sub

Private Sub InitBuf(Buf As WavBuf)
  If Buf.Hdr.dwUser Then Exit Sub
  With Buf.Hdr
    .dwUser = 1
    If .lpData = 0 Then .lpData = VarPtr(Buf.Arr(0))
    If .dwBufferLength = 0 Then .dwBufferLength = (UBound(Buf.Arr) + 1) * 4
    waveInPrepareHeader DevHandle, Buf.Hdr, Len(Buf.Hdr)
    waveInAddBuffer DevHandle, Buf.Hdr, Len(Buf.Hdr)
  End With
End Sub

Private Sub ProcessBuf(Buf As WavBuf)
  waveInUnprepareHeader DevHandle, Buf.Hdr, Len(Buf.Hdr)
  Buf.Hdr.dwFlags = 0
  Buf.Hdr.dwUser = 0
 'your Buffer-Handling-Code here
End Sub

Private Function CIdx&(ByVal Idx&)
  CIdx = Idx Mod (UBound(RBuf) + 1)
End Function
Olaf