我正在尝试编写一个从计算机上的默认录音设备接收声音的应用程序。当运行从托管代码访问DirectX的任何代码时,我收到此错误:
DLL'C:\ Windows \ assembly \ GAC \ Microsoft.DirectX.DirectSound \ 1.0.2902.0__31bf3856ad364e35 \ Microsoft.DirectX.DirectSound.dll'正在尝试在OS Loader锁内执行托管执行。不要尝试在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()
答案 0 :(得分:2)
在托管环境之外,c ++在加载器锁中执行代码的最简单方法之一是在dll中嵌入类,在全局范围内执行初始化。
执行dll对象初始化的唯一时间是来自OS的DllMain消息 - 但在这些消息期间,加载程序锁定处于活动状态。加载程序锁可以防止不同的线程同时加载dll进入单个dll的DllMain。
要解决这个问题在C ++(以及可能是托管环境)中非常困难,因为在dll中可能需要构建许多隐式对象。尽管如此,您需要找到从DllMain调用的初始化代码,并确保它从显式初始化/关闭函数调用dll导出,或者即时完成。