Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如果某个对象已被释放,那么抑制gc终结器是否会节省一些时间?_C#_Garbage Collection_Dispose - Fatal编程技术网

C# 如果某个对象已被释放,那么抑制gc终结器是否会节省一些时间?

C# 如果某个对象已被释放,那么抑制gc终结器是否会节省一些时间?,c#,garbage-collection,dispose,C#,Garbage Collection,Dispose,垃圾收集可能会成为一个耗时的过程。在这方面,GC往往只在必要时工作。如果对象已被释放,为了帮助节省时间和帮助GC,是否应该抑制GC的终结器 using(var sO = new someObject()) { //work with object } public class someObject : IDisposable { internal Stream someResource; internal Context someContext; public void Dis

垃圾收集可能会成为一个耗时的过程。在这方面,GC往往只在必要时工作。如果对象已被释放,为了帮助节省时间和帮助GC,是否应该抑制GC的终结器

using(var sO = new someObject())
{
 //work with object
}

public class someObject : IDisposable
{
  internal Stream someResource;
  internal Context someContext;

  public void Dispose()
  {
   someContext.Dispose();
   someResource.Dispose();
   //A: does suppressing the GC finalizer here save time for the GC?
   //B: can this cause memory leaks?
   //GC.SuppressFinalize(this);
  }
}

如果您主动地
处置
一个对象,那么是的,您应该抑制终结。如果您主动/决定性地释放所有资源,则无需最终确定对象。让它挂在终结器上只是浪费时间

为了澄清一些困惑:

  • 只有在需要以某种特殊方式清理非托管资源时,才需要终结器

  • 如果没有非托管资源,则不需要终结器

  • 如果您有一个终结器,那么您肯定应该实现IDisposable

  • 如果您有一个终结器,那么应该在Dispose中调用GC.SuppressFinalize,因为如果您自己已经清理了终结器,则不需要调用终结器

  • 如果有终结器,只需调用GC.SuppressFinalize。如果你不这样做,你可能还是想把它称为防御措施

在这里抑制GC终结器是否为GC节省时间

如果存在非托管资源且对象具有终结器,则为“是”;如果不禁止此操作,对象可能会在终结队列中存在很长时间。您处置的资源也可能需要很长时间才能完成(例如,关闭昂贵的I/O通道)

如果您没有终结器,您是说您没有任何未管理的东西需要清理。作为一种防御措施,您仍然应该调用SuppressFinalize

根据FxCop规则:

“未能抑制终结会降低性能,且不会带来任何好处。”


至于你的另一个问题

这会导致内存泄漏吗

在本例中,如果任何资源处于非托管状态,则为“是”。如果您的对象在有机会调用
Dispose
之前以某种不寻常的方式终止,则无法正确释放非托管资源。考虑一下,如果<代码> SAMRESURCE <代码>是非托管的,在使用<代码>某个对象< /代码>实例时抛出异常。


如果您的对象持有非托管资源,并且您需要保证这些资源被清理,那么您也需要一个终结器(在您的情况下,它将被命名为
~someObject
)。

还有一点没有提到:一个对象只需要被认为是“活动的”如果存在某个执行路径,代码可能需要通过该路径访问其字段或对象头(保存有关对象类型的信息的数据结构,是否用作监视锁等),如果对象字段持有非托管句柄,
Dispose
方法做的最后一件事是关闭句柄,当
Dispose
方法运行时,对象可能有资格完成。哎呀。调用
GC.SuppressFinalize
不仅可以防止终结器在执行后排队;将其放置为
Dispose
的最后一件事将阻止对象在执行之前符合终止条件。

可能重复@Mr.disposition-这是一个不错的线程,但它没有任何时间覆盖。我很好奇,调用GC.superssFinalize是否能节省大量时间。与GC正在执行的其他操作相比,所浪费的时间是否很长,或者将是几分钟?@TravisJ单个对象的浪费可能微不足道,但在某些情况下,这肯定会增加。绝对没有理由不这样做:)只是为了添加:另外,在终结器运行之前,对象的内存不会被回收。@JaredPar-MSDN声明“实现IDisposable接口的对象可以从IDisposable.Dispose方法调用此方法,以防止垃圾收集器调用对象。在不需要它的对象上完成。”。“但是,如果没有像本例中那样定义终结器,该怎么办?在某些情况下,比执行终结器所需时间更大的问题是,每个对象都有一个终结器,以及这样的对象对其拥有直接或间接引用的每个对象,必须保留在内存中,直到完成或抑制终结器。由于.net使用分代垃圾回收器,如果无法抑制终结器,可能会导致对象在内存中保留的时间比它们应该保留的时间长得多;但是,在禁止终结时,应包括终结器作为备份,以防出现错误。很抱歉再次重复,但这是正确的吗?不,相反。如果您需要一个终结器,那么您需要一个GC.SuppressFinalize。很少需要终结器;你只需要在特殊的、非托管的资源无法自行清理时才需要它。我用一些经验法则更新了我的答案。希望这能为你解决问题。