2010-09-23 93 views
8

我有一个视图模型,用作我的自定义控件的数据源。在视图模型的构造函数中,我设置了一个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; 
     } 
    } 
} 
+0

会很高兴知道你在用什么语言工作;)但无论如何......一个“视图模型”?听起来像你是有点混合的东西,应该真的分开... – 2010-09-23 18:08:10

+0

我使用的是C#。我正在为WPF的目录选择器控件工作,并且此控件必须能够处理驱动器挂载和卸载以及cd-rom插入/删除。由于MVVM是将UI与代码分开的首选方式,因此我使用视图模型返回驱动器,目录等列表并监视驱动器。 – akonsu 2010-09-23 18:12:14

回答

4

这篇文章有解决方案:Disposing WPF User Controls

基本上,似乎WPF DOS没有在任何地方使用IDisposable接口,让应用程序需要清理自己明确。所以在我的情况下,我从我的控件订阅Dispatcher.ShutdownStarted事件,该事件使用需要处理的视图模型,并从事件处理程序中处置控件的DataContext。