I pushed a new version after lots of probing of native behaviour.
I'm still keeping the event queue alive after shutdown to raise a final event. Wrapped media source tests in Windows show that native does not use this method. I made an async shutdown test which consistently caused hanging in Wine without the last commit here. Native didn't hang unless the wrapper was used, but no `EndGetEvent()` failures occurred. The reason for hanging with a wrapped source wasn't visible, but maybe native uses a private interface for notification and the source object included in the notification doesn't match the wrapped object the session stores.
I looked into the undocumented interface mentioned above. The native session calls a method which takes a result pointer and writes a COM object pointer to that location. The second call takes a COM object pointer, and the session passes the pointer returned by the first call. If that call failed, it apparently creates an object and passes that. I was unable to determine the object type, but it wasn't `IMFAsyncCallback`, `IMFMediaEvent`, `IMFMediaStream` or `IMFAsyncResult`.
I haven't used a private interface here, but will use one if it's deemed necessary. `EndGetEvent()` can fail without the hack used here, and it's just a matter of timing if the callback is invoked or not, so it's not possible for the app to prove if the callback "should" or "should not" have been invoked.