问题标签 [finalizer]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
.net - .net 终结器是否总是执行?
终结器是否保证在某些时候(备用断电等)在 .NET 中执行?我知道 GC 是如何工作的,并且它们何时运行是不确定的。
(搜索没有显示好的答案,所以我添加了这个问题,希望与不太容易发现的实际答案合并。除此之外,我已经知道答案并将添加几天后它以防万一没有人提到它。)
.net - SqlConnection 会被 GC 处理掉吗?
免责声明:我知道IDisposable
在处理非托管资源时应该实施。其余的代码应该是确定性的并且做using (...) { }
(相当于try {} finally { Dispose(); }
)以保证尽快清理。此外,GC不会调用Dispose()
,因此推荐的模式是覆盖Finalize()
然后调用Dispose()
. GC 通常会调用Finalize()
(除非GC.SuppressFinalize()
已调用)。
问题:using (SqlConnection...) { }
所以现在我解决了这个问题,我遇到了一个奇怪的情况,由于代码超出我的控制,我无法做到这一点。我通常可以做一个确定性的Dispose()
,但不能保证。我使用 Reflector 进行反汇编SqlConnection
,发现它使用了 Dispose(),但除非我是盲人,否则没有终结器/析构函数(Finalize()
或~SqlConnection()
)。这是否意味着在我不能的奇怪情况下,GC 不会“清理”(发送回池)连接?我一直找不到任何确定的...
.net - 使用 Excel 互操作时出现 InvalidComObjectException
在以下代码中关闭我的应用程序后,我得到一个 InvalidComObjectException:
这是为什么?我不应该使用终结器来处理 COM 对象吗?
c# - 使用 Dispose() 或终结器清理托管线程?
假设我在 C++0x 中有一个消息泵类,如下所示(注意,SynchronizedQueue 是 function<void()> 的队列,当您在队列上调用 receive() 并且它为空时,它会阻塞调用线程,直到有一件物品要退货):
我已将此类转换为 C#,但我对析构函数中的代码有疑问。根据 IDisposable 模式,我应该只提供一个 Dispose() 方法来释放托管和非托管资源。
我应该将 C++ 析构函数代码放入:
- 应用程序退出时客户端需要调用的自定义 CleanUp() 方法?如果客户忘记了怎么办?
- IDisposable 的 Dispose() 方法,以便客户端也可以调用它?但是,如果客户忘记了怎么办?
- 在 C# 终结器方法内部,它会始终执行吗?我读到如果您没有任何非托管资源,则不应包含终结器方法,因为它会损害性能。
- 无处?只是忽略标记 done_ 标志而让 GC 自然处理它,因为 Thread 对象是托管资源?这样线程会被强制中止吗?
我还发现,如果我不将在构造函数中创建的消息泵线程标记为后台线程,我的 MessagePump 对象永远不会被 GC 处理,并且应用程序在退出时只会挂起。这是什么原因?
c# - 在 C# 中自动删除 COM 事件处理程序
我有一个独立的 .exe COM 服务器和一个简单的 C# 测试程序,它启动一个服务器实例并在之后立即关闭它。奇迹般有效。但是,如果我关闭 C# 程序本身,我会在终结器运行期间遇到异常,因为它试图从不再运行的 COM 服务器中注销/取消通知 COM 事件接收器。
异常是
“在 mscorlib.dll 中发生 System.Runtime.InteropServices.InvalidComObjectException 类型的第一次机会异常”
调用堆栈:
mscorlib.dll!System.Runtime.InteropServices.ComEventsSink.Unadvise() + 0x20 字节 mscorlib.dll!System.Runtime.InteropServices.ComEventsSink.RemoveAll(System.Runtime.InteropServices.ComEventsSink sinks) + 0x11 字节
mscorlib。 dll!System.Runtime.InteropServices.ComEventsInfo.Finalize() + 0x18 字节
我可以通过在关闭服务器之前手动删除 COM 事件处理程序来修复此错误。即 myComServer.OnFunkyEvent -= OnFunkyEventHandler; 但是,我发现这不雅、容易出错且乏味。所以问题是,我能否以某种方式手动触发我的 COM 事件的 RemoveAll() 调用,使其不会在终结器中运行?
java - 如果终结器使对象可访问怎么办?
在 Java 中,finalize
当一个对象即将被垃圾回收时(即覆盖它)被调用,因此当它无法访问时。但是如果终结器使对象再次可访问怎么办,那会发生什么?
c# - 终结器和 IDisposable
根据文档(MSDN:链接),很明显在实现终结器时应该使用 IDisposable 模式。
但是,如果您实现了 IDisposable(以便提供一种确定性的方式来处理对象),并且您没有任何非托管资源要清理,您是否需要实现终结器?
如我所见,如果该类只有托管资源并且您不调用 Dispose,则托管资源将自动被 GC 清理,因此无需实现终结器。我错了吗?
另外,如果我使用我的 Dispose 方法来清理事件处理程序会怎样。由于 Dispose 不会自动被 GC 调用,我是否应该实现终结器以确保事件处理程序不连线?
.net - 我可以防止另一个 AppDomain 中未捕获的异常关闭应用程序吗?
我遇到了一个行为不端的库,它在终结器中引发异常,这当然会使应用程序崩溃。
为了避免这种情况,我尝试将库加载到它自己的 AppDomain 中,但异常仍然浮出水面并使应用程序崩溃。
正如 MSDN 上所记录的,注册到AppDomain.UnhandledException
并不能防止异常冒泡,但我很惊讶没有其他方法可以在“子 AppDomain”中捕获此类异常。
插件主机或使用 AppDomain 对可能有害的代码进行沙箱处理的应用程序如何阻止未处理的异常?事实上可能吗?
注意:我已经有另一种解决方法,这里描述的那个。坏的终结器位于一个长期存在的对象上,该对象似乎只在关闭期间被收集,因此向用户隐藏这个“虚假”错误就足够了。不过,我发现这种解决方法很脆弱,因为它要么隐藏其他真正的错误,要么如果早点收集对象,就有可能炸毁我的应用程序。
c# - AppDomain.Unload 抛出终结器?
所以这是到目前为止的故事,我有一个使用 AppDomain 执行某些任务的工作人员。该域的设置和拆卸成本很高。因此,我为工作人员创建了每个线程的 WeakReference 对象缓存,如下所示:
我遇到的问题是,当 GC 收集时,似乎总是在调用 AppDomain.Unload 时抛出异常:
所以我认为这很奇怪,我知道我在那个域中没有任何“正在运行”的东西......有什么关系?一些挖掘和反复试验我想出了这个:
所以我的问题是:
- AppDomain.Unload 是否总是从终结器失败?为什么?
- 通过上述解决方法,我会遇到任何“不受欢迎”的事情吗?
c# - 在 C# 中使用终结器的好示例
当我阅读了几篇关于 C# 中内存管理的文章时,我对 Finalizer 方法感到困惑。
有很多复杂的规则与之相关。例如,没有人知道终结器何时会被调用,即使 ctor 中的代码抛出,它们也会调用,CLR 不保证在程序关闭时调用所有终结器等。
在现实生活中可以使用哪些终结器?
我发现的唯一一个例子是 GC 启动时发出哔哔声的程序。
您是否在代码中使用终结器并且可能有一些好的示例?
升级版:
当开发人员想要确保某些类始终通过 IDisposable 正确处理时,可以使用终结器。(链接;感谢史蒂夫汤森)