2

我已经构建了一个使用ManagementEventWatcher该类的 .net 库。我的库是一次性的,所以通常我会将它包装在 using 语句中,并且ManagementEventWatcher该类将由我的库处理。

我的问题是我的库暴露给 COM,并在不使用一次性模式的 VB6 中使用。如果用户没有从他们的 .net 应用程序中调用库上的 dispose,或者由于 VB6 而不能调用,则该类将从内部ManagementEventWatcher抛出一个InvalidComObjectExceptionSinkForEventQuery.Cancel

我无法捕获异常,所以它仍然未处理,这不好。我可以尝试一些解决方法吗?

System.Runtime.InteropServices.InvalidComObjectException was unhandled
  Message=COM object that has been separated from its underlying RCW cannot be used.
  Source=mscorlib
  StackTrace:
       at System.StubHelpers.StubHelpers.StubRegisterRCW(Object pThis, IntPtr pThread)
       at System.Management.IWbemServices.CancelAsyncCall_(IWbemObjectSink pSink)
       at System.Management.SinkForEventQuery.Cancel()
       at System.Management.ManagementEventWatcher.Stop()
       at System.Management.ManagementEventWatcher.Finalize()
  InnerException: 
4

1 回答 1

0

我今天也遇到了同样的问题,基本上我无法在类上调用 dispose 并且 WMI 对象没有被释放,给了我同样的错误。

我最终所做的是实现了一个不同的接口而不是 IDisposable,公开了两个方法:Init 和 TearDown,并使用这些方法来设置我的 MEW 并处理它。不过,这有点 hack,如果该类的用户不知道这一点,他将永远不会调用这两个方法,并且您的 MEW 将永远不会启动或被处置。

另一种方法可能是让类连接到像“OnDestroy”这样的事件,并通过拆除 MEW 对象来做出相应的响应。

    public void Init()
    {
        if (mew == null)
        {
            mew = new ManagementEventWatcher(query);
            mew.EventArrived += mew_EventArrived;
            mew.Start();
        }
    }

    public void TearDown()
    {
        if (mew != null)
        {
            mew.Stop();
            mew.Dispose();
            mew = null;
        }
    }

编辑:是的,我意识到这不是您正在寻找的答案,我认为无论如何都没有办法避免这种情况,用户必须知道如何使用该类...:/

于 2011-03-23T13:46:00.037 回答