views:

387

answers:

1

I am trying to write an application that takes in sound from the default audio recording device on a computer. When running any code that accesses DirectX from my managed code i get this error:

DLL 'C:\Windows\assembly\GAC\Microsoft.DirectX.DirectSound\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.DirectSound.dll' is attempting managed execution inside OS Loader lock. Do not attempt to run managed code inside a DllMain or image initialization function since doing so can cause the application to hang.

DevicesCollection coll = new DevicesCollection();

and

Device d = new Device(DSoundHelper.DefaultCaptureDevice);

and

Capture c = new Capture(DSoundHelper.DefaultCaptureDevice);

all cause the LoaderLock MDA to pop up and tell me there is a problem. I have scoured the internet (stackoverflow included) for solutions to this problem, but most people just say to turn off the warning, which does not work. When I turn off the warning, a generic ApplicationException is thrown, which is even less useful. I have seen the answers to this question as well, which didn't help because he said to remove the code that is causing the error. Others have said "fix your code."

My questions are:

how can I call any (preferably managed) DirectX code from C# without getting this error?

edit: this is the stack trace I get:

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  A: 

Outside of the managed environment, one of the easiest ways in c++ to execute code within the loader lock is to have classes embedded in dll's performing their initialization at global scope.

The only time to do the initialization of dll objects is during the DllMain messages from the OS - but during these messages the loader lock is active. the loader lock prevents different threads loading dll's entering a single dll's DllMain at the same time.

To fix the issue is quite difficult in C++ (and, presumably managed environments) as there are possibly many implicit objects needing construction in a dll. Nonetheless, you need to find the initialization code thats being called from DllMain, and ensure that, well, its called from explicit initialization / shutdown functions the dll exports, or done just-in-time.

Chris Becke