Я пишу приложение на C #, .NET 3.0 в VS2005 с функцией мониторинга вставки / извлечения различных съемных носителей (USB-флеш-накопители, CD-ROM) и т.д.). Я не хотел использовать WMI, поскольку иногда он может быть неоднозначным (например, он может порождать несколько событий вставки для одного USB-накопителя), поэтому я просто переопределяю WndProc моей основной формы, чтобы поймать сообщение WM_DEVICECHANGE, как предлагается здесь . Вчера я столкнулся с проблемой, когда выяснилось, что мне все равно придется использовать WMI для получения некоторых непонятных сведений о диске, таких как серийный номер. Оказывается, вызов подпрограмм WMI из WndProc вызывает MDA DisconnectedContext.
Покопавшись, я нашел неудобный обходной путь. Код выглядит следующим образом:
// 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, в отдельном потоке, но затем ожидание ее завершения.
Теперь вопрос: почему это работает, и почему так должно быть? (или не так ли?)
Я не понимаю факта получения MDA DisconnectedContext или RPC_E_WRONG_THREAD в первую очередь. Чем отличается выполнение процедуры GetDrives ()
из обработчика события нажатия кнопки от ее вызова из WndProc? Разве они не происходят в одном и том же основном потоке моего приложения? Кстати, мое приложение полностью однопоточное, так почему же вдруг возникла ошибка, относящаяся к какой-то «неправильной нити»? Подразумевает ли использование WMI многопоточность и особую обработку функций из System.Management?
Тем временем я нашел еще один вопрос, связанный с этим MDA, это здесь . Хорошо, я могу понять, что вызов WMI означает создание отдельного потока для базового COM-компонента, но мне все еще не приходит в голову, почему не требуется никакого волшебства при его вызове после нажатия кнопки, а при вызове требуется магия это из WndProc.
Я действительно смущен этим и был бы признателен за некоторые разъяснения по этому поводу. Есть только несколько вещей хуже, чем иметь решение и не знать, почему оно работает: /
Ура, m действительно смущен этим и был бы признателен за некоторые разъяснения по этому поводу. Есть только несколько вещей хуже, чем иметь решение и не знать, почему оно работает: /
Ура, m действительно смущен этим и был бы признателен за некоторые разъяснения по этому поводу. Есть только несколько вещей хуже, чем иметь решение и не знать, почему оно работает: /
Ура, Александр