如何正确清理视图模型?

发布于 2024-09-24 12:48:20 字数 1345 浏览 3 评论 0原文

我有一个视图模型,用作自定义控件的数据源。在视图模型的构造函数中,我设置了一个 WMI ManagementEventWatcher 并启动它。我的视图模型实现了 IDisposable,因此我在 Dispose 方法中停止了观察器。

当我将自定义控件嵌入到窗口中,然后关闭窗口以退出应用程序时,它会抛出 InvalidComObjectException ,指出“无法使用已与其底层 RCW 分离的 COM 对象”。这是因为我的观察者而发生的,如果我不创造它,也不例外。没有关于异常的附加信息,例如堆栈跟踪等。

我的猜测是,某些东西会保留视图模型,直到观察者使用的线程终止但在观察者停止之前,我不知道如何处理这个问题。

有什么建议吗? 谢谢 康斯坦丁

public abstract class ViewModelBase : IDisposable, ...
{
    ...

    protected virtual void OnDispose() { }

    void IDisposable.Dispose()
    {
        this.OnDispose();
    }
}

public class DirectorySelector : ViewModelBase
{
    private ManagementEventWatcher watcher;

    private void OnWMIEvent(object sender, EventArrivedEventArgs e)
    {
        ...
    }

    protected override void OnDispose()
    {
        if (this.watcher != null)
        {
            this.watcher.Stop();
            this.watcher = null;
        }
        base.OnDispose();
    }

    public DirectorySelector()
    {
        try
        {
            this.watcher = new ManagementEventWatcher(new WqlEventQuery(...));

            this.watcher.EventArrived += new EventArrivedEventHandler(this.OnWMIEvent);
            this.watcher.Start();
        }
        catch (ManagementException)
        {
            this.watcher = null;
        }
    }
}

I have a view model that is used as the data source for my custom control. In the view model's constructor I set up a WMI ManagementEventWatcher and start it. My view model implements IDisposable, so I stop the watcher in the Dispose method.

When I embed the custom control into a window, and then close the window to exit the application it throws an InvalidComObjectException saying "COM object that has been separated from its underlying RCW cannot be used". This happens because of my watcher, and if I do not create it, there is no exception. there is no additional information about the exception such as stack trace, etc.

My guess is that something keeps the view model until the thread that the watcher uses terminates but before the watcher is stopped, and I do not know how to handle this.

Any advice?
Thanks
Konstantin

public abstract class ViewModelBase : IDisposable, ...
{
    ...

    protected virtual void OnDispose() { }

    void IDisposable.Dispose()
    {
        this.OnDispose();
    }
}

public class DirectorySelector : ViewModelBase
{
    private ManagementEventWatcher watcher;

    private void OnWMIEvent(object sender, EventArrivedEventArgs e)
    {
        ...
    }

    protected override void OnDispose()
    {
        if (this.watcher != null)
        {
            this.watcher.Stop();
            this.watcher = null;
        }
        base.OnDispose();
    }

    public DirectorySelector()
    {
        try
        {
            this.watcher = new ManagementEventWatcher(new WqlEventQuery(...));

            this.watcher.EventArrived += new EventArrivedEventHandler(this.OnWMIEvent);
            this.watcher.Start();
        }
        catch (ManagementException)
        {
            this.watcher = null;
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瞳孔里扚悲伤 2024-10-01 12:48:20

本文有解决方案: 处置 WPF 用户控件

基本上,WPF 似乎没有在任何地方使用 IDisposable ,因此应用程序需要显式地自行清理。因此,就我而言,我从使用需要处置的视图模型的控件订阅 Dispatcher.ShutdownStarted 事件,并从事件处理程序处置控件的 DataContext。

this article has the solution: Disposing WPF User Controls

basically, WPF dos not seem to use IDisposable anywhere, so the app needs to cleanup itself explicitly. so in my case, i subscribe to the Dispatcher.ShutdownStarted event from my control that uses the view model that needs to be disposed, and dispose the control's DataContext from the event handler.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文