在我的代码中,我有一个创建新线程的类。这个新线程有一个Dispatcher,因此除非我调用
,否则线程不会完成Dispatcher.CurrentDispatcher.InvokeShutdown();
线程不能在我的课外引用。 所以我在想:当我的对象被垃圾收集时,如何确保我的线程完成?
一个响应是使用IDisposable,但是如果有人忘记调用Dispose(),那么该线程将永远不会停止,因此它不是解决方案。
另一个响应是两个使用Dispose + Destructor,但我听说我们应该只使用析构函数来释放非托管资源。我走到了尽头。
什么是最佳解决方案?
答案 0 :(得分:2)
一种选择是仅对调试版本使用终结器。不要让它“很好地”关闭线程:让它非常突出地记录警告。这应该可以帮助您隔离您忘记妥善处理对象的地方。
然而,它并非万无一失,而且它具有使调试和发布代码不同的不良特性。
您的调度员通常会经常接收事件吗?如果长时间没有收到任何事件,你能否至少记录一下警告?
一个相当讨厌的选择是让调度员对一次性对象有一个弱引用。它可以定期检查对象是否已被垃圾收集(使用WeakReference.IsAlive
)并自行关闭(如果是这样)。同样,这不是非常令人愉快(并且应该记录警告)。
答案 1 :(得分:1)
“Dispose + Destructor”解决方案对我来说似乎很好。正如乔恩所说,你可以采用一些技巧来检测是否错过了一次Dispose呼叫,但是在终结器呼叫中停止线程将是一个额外的保护措施。
顺便说一句,线程是一种非托管资源。
答案 2 :(得分:1)
关于处置和最终确定here有很多有用的信息。显然,如果您正在编写可重用的类或库以供其他程序员使用,您不能假设将始终调用Dispose方法,因此实现终结器是明智的:
public void Dispose() {
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing) {
if (disposing) {
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
}
~MyClass() {
Dispose (false);
}
似乎 在这种情况下,您有以下选择:
Dispose
你可以通过保护它们来防止最后2个被编译到发行版中:
~MyClass() {
Dispose (false);
#if DEBUG
// log a warning or scream at the developer in some way
#endif
}