Tôi viết một ứng dụng trong C#, .NET 3.0 trong VS2005 với tính năng giám sát chèn/đẩy các ổ đĩa di động khác nhau (đĩa flash USB, CD-ROM, v.v.). Tôi không muốn sử dụng WMI, vì nó có thể đôi khi không rõ ràng (ví dụ: nó có thể sinh ra nhiều sự kiện chèn cho một ổ đĩa USB), vì vậy tôi chỉ cần ghi đè WndProc của biểu mẫu chính để nhận thông báo WM_DEVICECHANGE, như được đề xuất here. Hôm qua tôi gặp phải vấn đề khi nó bật ra rằng tôi sẽ phải sử dụng WMI anyway để lấy một số chi tiết đĩa tối nghĩa như một số serial. Nó chỉ ra rằng gọi WMI thói quen từ bên trong WndProc ném DisconnectedContext MDA.DisconnectedContext MDA khi gọi các hàm WMI trong ứng dụng đơn luồng
Sau một số lần đào, tôi đã kết thúc với một giải pháp khó xử cho điều đó. Mã này như sau:
// 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();
về cơ bản có nghĩa là chạy quy trình liên quan đến WMI trên một sợi riêng biệt - nhưng sau đó, chờ đợi hoàn thành.
Bây giờ, câu hỏi là: lý do tại sao hoạt động và tại sao phải làm như vậy? (hoặc, phải không?)
Tôi không hiểu thực tế nhận được DisconnectedContext MDA hoặc RPC_E_WRONG_THREAD ở địa điểm đầu tiên. Làm thế nào để chạy thủ tục GetDrives()
từ trình xử lý sự kiện nhấn nút khác với việc gọi nó từ WndProc? Chúng không xảy ra trên cùng một chuỗi chính của ứng dụng của tôi? BTW, ứng dụng của tôi là hoàn toàn đơn luồng, vậy tại sao tất cả các lỗi đột ngột đề cập đến một số 'sai thread'? Việc sử dụng WMI ngụ ý đa luồng và xử lý đặc biệt các chức năng từ System.Management?
Trong thời gian chờ đợi, tôi đã tìm thấy một câu hỏi khác liên quan đến MDA đó, đó là here. OK, tôi có thể gọi nó là WMI có nghĩa là tạo ra một chuỗi riêng biệt cho thành phần COM cơ bản - nhưng nó vẫn không xảy ra với tôi tại sao không cần có ma thuật khi gọi nó sau khi nhấn nút và thực hiện phép thuật khi gọi nó từ WndProc.
Tôi thực sự bối rối về điều đó và sẽ đánh giá cao một số làm rõ về vấn đề đó. Chỉ có một vài tồi tệ hơn mọi thứ vì phải một giải pháp và không biết lý do tại sao nó hoạt động:/
Chúc mừng, Aleksander
Cùng một sự cố ở đây! Tôi ước có một giải pháp. Tôi sẽ thêm tiền thưởng ... có lẽ điều đó sẽ giúp ích. – Brad