代码之家  ›  专栏  ›  技术社区  ›  Scott M.

检测到LoaderLock,关闭警告没有帮助

  •  1
  • Scott M.  · 技术社区  · 14 年前

    我正在尝试编写一个应用程序,从计算机上的默认录音设备接收声音。当运行任何从托管代码访问DirectX的代码时,我会遇到以下错误:

    DLL'C:\Windows\assembly\GAC\Microsoft。DirectX。DirectSound\1.0.2902.0__31bf3856ad364e35\Microsoft。DirectX。直接声音。“dll”正在OS加载程序锁内尝试托管执行。不要试图在DllMain或映像初始化函数中运行托管代码,因为这样做可能会导致应用程序挂起。

    DevicesCollection coll = new DevicesCollection();
    

    Device d = new Device(DSoundHelper.DefaultCaptureDevice);
    

    Capture c = new Capture(DSoundHelper.DefaultCaptureDevice);
    

    所有这些都会导致LoaderLock MDA弹出并告诉我有问题。我在互联网上搜索(包括stackoverflow)来寻找这个问题的解决方案,但大多数人只是说关闭警告,这是行不通的。当我关闭警告时,会抛出一个通用的ApplicationException,它甚至没有那么有用。我已经看到了答案 this question 同样,这也没有帮助,因为他说要删除导致错误的代码。还有人说“修复你的代码”

    我的问题是:

    如何从C#调用任何(最好是托管的)DirectX代码而不出现此错误?

    编辑:这是我得到的堆栈跟踪:

    at Microsoft.DirectX.DirectSound.Device..ctor(Guid guidDev)
    at Autotuner.fMain.button1_Click(Object sender, EventArgs e) in C:\\Users\\Scott\\Documents\\Visual Studio 2008\\Projects\\Autotuner\\Autotuner\\Form1.cs:line 17
    at System.Windows.Forms.Control.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnClick(EventArgs e)
    at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
    at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    at System.Windows.Forms.Control.WndProc(Message& m)
    at System.Windows.Forms.ButtonBase.WndProc(Message& m)
    at System.Windows.Forms.Button.WndProc(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    at System.Windows.Forms.Application.Run(Form mainForm)
    at Autotuner.Program.Main() in C:\\Users\\Scott\\Documents\\Visual Studio 2008\\Projects\\Autotuner\\Autotuner\\Program.cs:line 18
    at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
    at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    at System.Threading.ThreadHelper.ThreadStart()
    
    1 回复  |  直到 5 年前
        1
  •  2
  •   Chris Becke    14 年前

    在托管环境之外,C++中最简单的方法之一是在加载程序锁中执行代码,以便在DLL中嵌入类,在全局范围内执行初始化。

    初始化dll对象的唯一时间是在来自操作系统的DllMain消息期间,但在这些消息期间,加载程序锁处于活动状态。加载程序锁防止加载dll的不同线程同时进入单个dll的DllMain。

    在C++中(可能是托管环境)来修复这个问题是相当困难的,因为在DLL中可能需要构造许多隐式对象。尽管如此,您需要找到从DllMain调用的初始化代码,并确保它是从dll导出的显式初始化/关闭函数调用的,或者是及时完成的。