最近做一个winForm的小工具,用到了 ManagementObjectSearcher/ManagementClass 和 WndProc ,涉及到对 移动设备的检测。
窗体加载时会执行一个 Reload()方法(通过 ManagementObjectSearcher/ManagementClass 重新获取移动设备盘符),但是当把设备 拔出或插入时,由 WndProc 去执行 Reload() 方法,老是报 :
托管调试助手 "DisconnectedContext":“上下文 0xf20540 已断开连接。将不会使用代理来处理 COM 组件上的请求。这可能会导致损坏或数据丢失。要避免此问题,请确保在应用程序全部完成 RuntimeCallableWrapper (表示其内部的 COM 组件)之前,所有上下文/单元都保持活动状态。
怎么来解决这个问题?我也不知道,网上找了很久,没由合适的的解决办法。只有自己分析,去尝试解决了。。
通过调试,发现 Reload() 在三处有调用,窗体加载,设备插入,设备拔出。窗体加载时,Reload() 没有报错,正常加载,而当设备插入或拔出后,执行Reload() 就会报异常。
由此可见,可能好像是 不是一个线程 去执行 的 Reload() 导致,窗体加载时是UI线程 主线程 执行,而 插拔 执行的 WndProc 是另外的线程去执行。
在此,为了保证 Reload() 的 3处地方 执行都是一个线程去执行,怎么实现呢?看代码:
#region 检测可移动设备 public const int WM_DEVICECHANGE = 0x219; public const int DBT_DEVICEARRIVAL = 0x8000; public const int DBT_CONFIGCHANGECANCELED = 0x0019; public const int DBT_CONFIGCHANGED = 0x0018; public const int DBT_CUSTOMEVENT = 0x8006; public const int DBT_DEVICEQUERYREMOVE = 0x8001; public const int DBT_DEVICEQUERYREMOVEFAILED = 0x8002; public const int DBT_DEVICEREMOVECOMPLETE = 0x8004; public const int DBT_DEVICEREMOVEPENDING = 0x8003; public const int DBT_DEVICETYPESPECIFIC = 0x8005; public const int DBT_DEVNODES_CHANGED = 0x0007; public const int DBT_QUERYCHANGECONFIG = 0x0017; public const int DBT_USERDEFINED = 0xFFFF; /// <summary> /// 检测可移动设备 /// </summary> protected override void WndProc(ref Message m) { try { if (m.Msg == WM_DEVICECHANGE) { switch (m.WParam.ToInt32()) { case WM_DEVICECHANGE: break; case DBT_DEVICEARRIVAL://可移动设备 插入 isReload = true; break; case DBT_CONFIGCHANGECANCELED: break; case DBT_CONFIGCHANGED: break; case DBT_CUSTOMEVENT: break; case DBT_DEVICEQUERYREMOVE: break; case DBT_DEVICEQUERYREMOVEFAILED: break; case DBT_DEVICEREMOVECOMPLETE: //可移动设备 卸载 isReload = true; break; case DBT_DEVICEREMOVEPENDING: break; case DBT_DEVICETYPESPECIFIC: break; case DBT_DEVNODES_CHANGED: break; case DBT_QUERYCHANGECONFIG: break; case DBT_USERDEFINED: break; default: break; } } } catch (Exception ex) { MessageBox.Show((ex.InnerException ?? ex).ToString(), "检测可移动设备时出错", MessageBoxButtons.OK, MessageBoxIcon.Warning); } base.WndProc(ref m); } #endregion