DisconnectedContext MDAを呼び出す時にWMI機能を単一のネジ付きの応用
-
29-09-2019 - |
質問
書いているアプリクライアントまで、フルのC#.純3.0ではVS2005、モニターの挿入/排出の様々な着脱可能なドライブ(USBディスク、CD-Romなど)。たかったわけではありません利用でWMIることもあるのですが曖昧などでは産卵の複数の挿入イベントのためのシングルをUSBメモリ)かだけをオーバーライドWndProcのmainformをWM_DEVICECHANGEメッセージとして提案 こちらの.昨日実行し込の場合の問題であったことが判明したっているのかわからない難しい利用でWMIとにかく取得の一部を曖昧にディスクの内容などのシリアル番号です。ここで示されているデータ呼び出しでWMIのルーチンの中からWndProcすのDisconnectedContext MDA.
その後も掘っ終わせているんじゃないでしょ回避策です。コードは以下のとおりです:
// the function for calling WMI
private void GetDrives()
{
ManagementClass diskDriveClass = new ManagementClass("Win32_DiskDrive");
// THIS is the line I get DisconnectedContext MDA on when it happens:
ManagementObjectCollection diskDriveList = diskDriveClass.GetInstances();
foreach (ManagementObject dsk in diskDriveList)
{
// ...
}
}
private void button1_Click(object sender, EventArgs e)
{
// here it works perfectly fine
GetDrives();
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == WM_DEVICECHANGE)
{
// here it throws DisconnectedContext MDA
// (or RPC_E_WRONG_THREAD if MDA disabled)
// GetDrives();
// so the workaround:
DelegateGetDrives gdi = new DelegateGetDrives(GetDrives);
IAsyncResult result = gdi.BeginInvoke(null, "");
gdi.EndInvoke(result);
}
}
// for the workaround only
public delegate void DelegateGetDrives();
的なのでWMI関連の手続きは別のスレッドが待って完了します。
現在、問題は なぜ な仕組みになっているので、 なぜ ができる。(なのですか?)
かわからないものの、DisconnectedContext MDAはRPC_E_WRONG_THREAD。どのような走り GetDrives()
手続きからボタンをクリックイベントハンドラが異なるかを呼び出していることからWndProc?ない同じメインスレッドの私たします。ちなみに、私のアプリを完全に単一のネジ付き、なぜ突然のエラーを参照して間違ったスレッド'?なのでWMIを示唆するmultithreading、特例処理の機能からシステム。管理すれば良いのだろうか。
その間にこの他の問題に関連するMDAで こちらの.まぁでもこの呼び出しでWMIり構成する別個のスレッドのための基になるCOMコンポーネントも発生しないいかな-マジックが必要な場合を呼び出していることを後押しというマジックが必要な場合を呼び出していることからWndProc.
私は戸惑いみたい、との見方が一部明らかになる。数に限りありが悪化と有溶液とを知らないのはなぜで製作所/
声で Aleksander
解決
がかなり長いという議論のCOMアパートメッセージポンプ こちらの.その主なポイントの利益は、メッセージポンプを確保するために使用される通話は、駅の適切な整列化.以降、UIのスレッドが、駅からのメッセージが必要となる場合がある汲み上げるためのすべらない不具合を修正しました。
のWM_DEVICECHANGEメッセージで実際に送信されるウィンドウに複数の倍。その場合に呼び出すGetDrives直接、効果的に終わる再帰的に発信します。を入れてブレークポイントを解除GetDrives話しを添付してデバイスに火をつけます。
初めてございますのでご注意下さのポイントです。今F5を押し続けますのブレークポイント。この呼び出しスタックというように:
【睡眠、待ちに参加す] DeleteMeWindowsForms.エグゼク!DeleteMeWindowsForms.Form1.WndProc(refます。Windowsの場合です。ます。メッセージm)ライン46C# システム。Windows.Forms.dll!システム。Windowsの場合です。ます。ます。ControlNativeWindow.OnMessage(refます。Windowsの場合です。ます。メッセージm)+0x13バイト
システム。Windows.Forms.dll!システム。Windowsの場合です。ます。ます。ControlNativeWindow.WndProc(refます。Windowsの場合です。ます。メッセージm)+0x31バイト
システム。Windows.Forms.dll!システム。Windowsの場合です。ます。NativeWindow.DebuggableCallback(システム。IntPtr hWnd,int g,システム。IntPtr wparam,システム。IntPtr lparam)+0x64バイト [ィ管理推移]
[管理するネイティブ遷移]
mscorlib.dll!システム。Threading.WaitHandle.InternalWaitOne(システム。を行います。InteropServices.SafeHandle waitableSafeHandle、長millisecondsTimeout,bool hasThreadAffinity,bool exitContext)+0x2bバイト mscorlib.dll!システム。Threading.WaitHandle.WaitOne(int millisecondsTimeout,bool exitContext)+0x2dバイト
mscorlib.dll!システム。Threading.WaitHandle.WaitOne()+0x10バイト システム。Management.dll!システム。ます。MTAHelper.CreateInMTA(システム。タイプタイプ)+0x17bバイト
システム。Management.dll!システム。ます。ManagementPath.CreateWbemPath(string path)+0x18バイト システム。Management.dll!システム。ます。ManagementClass.ManagementClass(string path)+0x29バイト
DeleteMeWindowsForms.エグゼク!DeleteMeWindowsForms.Form1.GetDrives()ライン23+0x1bバイトのC#
での効果的に画面メッセージポンプによって汲み上げられて確保のためCOM話を適切に整列化すが、このドを呼び出すWndProcとGetDrivesましたが申請中のものでWM_DEVICECHANGEメッセージながらも前のGetDrivesます。ご利用の際はBeginInvoke、この再帰的ます。
再度、ブレークポイントのGetDrivesコF5を押した後の最初の時間です。次に、第二F5を押します。時にはまず、時にいびょうぶブレークポイントです。このときに、お客様のcallstackます。電話GetDrives、最後に端を列挙のdiskDriveListます。でも、メッセージを汲み上げを確保する通話整列化.
でピンポイントその MDA が考えられますが、再帰呼び出しで様のCOMコンテキストは取り壊さなければなり早び/またはオブジェクトで収集した前原COMオブジェクトが発売になります。