CSCore:收听音频会话事件时发生访问冲突

CSCore: access violation when listening to audio session events

我刚刚开始使用 CSCore,在学习了很多 C++ 之后又回到了 C#。这是一个测试程序,它枚举默认音频会话管理器的音频会话,并为每个会话附加一个空事件处理程序:

using System;
using CSCore.CoreAudioAPI;

class Program
{
    static void Main(string[] args)
    {
        using (var enumerator = new MMDeviceEnumerator())
        using (var device = enumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia))
        using (var sessionManager = AudioSessionManager2.FromMMDevice(device))
        using (var sessionEnumerator = sessionManager.GetSessionEnumerator())
        {
            foreach (var control in sessionEnumerator)
            {
                var control2 = control.QueryInterface<AudioSessionControl2>();
                RegisterAudioSession(control2);
            }
        }

        Console.WriteLine("Waiting...");
        Console.ReadKey();
    }

    static void RegisterAudioSession(AudioSessionControl2 session)
    {
        if (session.Process != null)
        {
            var events = new AudioSessionEvents();
            session.RegisterAudioSessionNotification(events);
        }
    }
}

我希望能够在此程序 运行 期间毫无问题地更改计算机的音量。但是,如果您尝试这样做,程序会因本机代码中的访问冲突而崩溃。这是堆栈跟踪:

>   AudioSes.dll!CLockedList<ATL::CComPtr<IAudioSessionEvents>,0,1>::ForEachEntry() Unknown
AudioSes.dll!CAudioSessionControl::OnAudioSessionEvent()    Unknown
AudioSes.dll!CAudioSessionControl::CAudioSessionNotificationDelegator::OnMediaNotification(struct MEDIA_NOTIFICATION_BLOCK *)   Unknown
MMDevAPI.dll!CMediaNotifications::OnMediaNotificationWorkerHandler(struct _TP_CALLBACK_INSTANCE *)  Unknown
MMDevAPI.dll!CMediaNotifications::MediaNotificationWorkerHandler(struct _TP_CALLBACK_INSTANCE *,void *) Unknown
ntdll.dll!TppSimplepExecuteCallback()   Unknown
ntdll.dll!TppWorkerThread() Unknown
kernel32.dll!@BaseThreadInitThunk@12()  Unknown
ntdll.dll!__RtlUserThreadStart()    Unknown
ntdll.dll!__RtlUserThreadStart@8()  Unknown

如果您删除对 RegisterAudioSessionNotification 的调用,则不会发生崩溃。

如果您注册了一个非空的事件处理程序,仍然会发生崩溃。

我尝试将 Console.ReadKey(); 移动到 using 块中以防释放必要的资源,但失败仍然存在。

我到处搜索解释和解决方案。 CSCore 的 github 页面上没有相关的未解决问题。我在某处读到本机代码的崩溃通常是由包装器程序集中的错误签名引起的。我将 CSCore 的 IAudioSessionEvents 上的所有方法与本机 IAudioSessionEvents 方法(枚举 here)进行了比较,但没有发现明显的差异。

This Firefox bug 是我在网上找到的对此特定堆栈跟踪的唯一参考,并且已解决。显然它已在 Flash Player 19.0.0.159 中得到解决,但据我所知,该源代码不可用于细读。

我是否忽略了代码中的错误,或者这是 CSCore 中的错误?

事实证明,如果目标平台是 32 位平台(或者在我的情况下,"Any CPU" 但在 32 位 VS 进程中 运行),则会发生此崩溃。切换到 64 位目标平台为我修复了它