I am wondering if it is possible to fall victim to issues around the management of managed threads in the native world when you marshal a callback delegate to a DLL through
Asynchronous procedure calls exist completely on the native side. APC's know nothing of managed threads nor of marshaling. NotifyServiceStatusChange would have to call (or use the equivalent of) QueueUserAPC to dispatch the APC, which only takes an native thread handle. So, the APC will be queued to the native thread that calls NotifyServiceStatusChange.
So this APC being queued and dispatched correctly rely on two things:
NotifyServiceStatusChange.You control neither of these two things.