托管调试助手 "DisconnectedContext":“上下文 0xf20540 已断开连接... 请确保在应用程序全部完成 RuntimeCallableWrapper (表示其内部的 COM 组件)之前,所有 COM 上下文/单元/线程都保持活动状态并可用于上下文转换

      最近做一个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
View Code
        /// <summary>
        /// 因为 Form_Load 与 WndProc 两个不同线程 去调用 ManagementClass 会报异常,故这里 开启一个线程去后台维护更新下拉框。
        /// </summary>
        public Thread thread = null;
        /// <summary>
        /// 是否重新加载 下拉框
        /// </summary>
        public bool isReload = false;
        private void MainForm_Load(object sender, EventArgs e)
        {
            thread = new Thread(Reload);
            thread.IsBackground = true;
            isReload = true;
            thread.Start();
        }
        /// <summary>
        /// 重新加载 移动硬盘盘符
        /// </summary>
        private void Reload()
        {
            while (true)
            {
                if (!isReload)
                {
                    Thread.Sleep(500);
                }
                else
                {
                   //这里编写业务逻辑代码。。。。。

         isReload = false; } } }

      注:使用 While True +  Thread.Sleep + 执行标识(isReload)  实现。

 

posted @ 2017-12-06 15:12  TakeTry  阅读(4299)  评论(0编辑  收藏  举报