如何正确清理视图模型?
我有一个视图模型,用作自定义控件的数据源。在视图模型的构造函数中,我设置了一个 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
本文有解决方案: 处置 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.