1

コンピューターのデフォルトのオーディオ録音デバイスからサウンドを取り込むアプリケーションを作成しようとしています。マネージド コードから DirectX にアクセスするコードを実行すると、次のエラーが発生します。

DLL 'C:\Windows\assembly\GAC\Microsoft.DirectX.DirectSound\1.0.2902.0__31bf3856ad364e35\Microsoft.DirectX.DirectSound.dll' は、OS ローダー ロック内でマネージ実行を試みています。DllMain またはイメージ初期化関数内でマネージ コードを実行しようとしないでください。実行すると、アプリケーションがハングする可能性があります。

DevicesCollection coll = new DevicesCollection();

Device d = new Device(DSoundHelper.DefaultCaptureDevice);

Capture c = new Capture(DSoundHelper.DefaultCaptureDevice);

いずれも LoaderLock MDA がポップアップし、問題があることを通知します。この問題の解決策をインターネット (stackoverflow を含む) で探しましたが、ほとんどの人は警告をオフにするように言っているだけで、うまくいきません。警告をオフにすると、一般的な ApplicationException がスローされますが、これはさらに役に立ちません。この質問への回答も見ましたが、エラーの原因となっているコードを削除するように言われたため、役に立ちませんでした。「コードを修正してください」と言う人もいます。

私の質問は次のとおりです。

このエラーを発生させずに 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()
4

1 に答える 1

2

管理された環境の外で、ローダーロック内でコードを実行するc ++の最も簡単な方法の1つは、グローバルスコープで初期化を実行するdllに埋め込まれたクラスを持つことです。

dllオブジェクトの初期化を行うのは、OSからのDllMainメッセージの間だけですが、これらのメッセージの間、ローダーロックはアクティブです。ローダーロックは、異なるスレッドがdllをロードして単一のdllのDllMainに同時に入るのを防ぎます。

この問題を修正することは、C ++(およびおそらく管理対象環境)では非常に困難です。dllでの構築が必要な暗黙のオブジェクトが多数存在する可能性があるためです。それでも、DllMainから呼び出されている初期化コードを見つけて、明示的な初期化/シャットダウン関数から呼び出され、dllがエクスポートするか、ジャストインタイムで実行されることを確認する必要があります。

于 2010-04-02T16:19:18.250 に答える