Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/291.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#Dispose模式的具体问题_C#_Dispose_Idisposable - Fatal编程技术网

关于C#Dispose模式的具体问题

关于C#Dispose模式的具体问题,c#,dispose,idisposable,C#,Dispose,Idisposable,关于C#中的Dispose模式,我有几个基本问题 在下面的代码片段中,这似乎是实现dispose模式的标准方法,您会注意到,如果disposing为false,则不会处理托管资源。如何/何时处理?GC是否会在以后处理托管资源?但是如果是这样,那么GG.SuppressFinalize(这个)调用做什么呢?有人能给我举一个处置托管资源的例子吗?脱钩事件浮现在脑海中。还有别的吗?按照模式的编写方式,如果您在“if(disposing)”部分中什么都不做,它们似乎会(稍后)被处理掉。评论 protec

关于C#中的Dispose模式,我有几个基本问题

在下面的代码片段中,这似乎是实现dispose模式的标准方法,您会注意到,如果disposing为false,则不会处理托管资源。如何/何时处理?GC是否会在以后处理托管资源?但是如果是这样,那么GG.SuppressFinalize(这个)调用做什么呢?有人能给我举一个处置托管资源的例子吗?脱钩事件浮现在脑海中。还有别的吗?按照模式的编写方式,如果您在“if(disposing)”部分中什么都不做,它们似乎会(稍后)被处理掉。评论

protected virtual void Dispose(bool disposing)
{  
    if (!disposed)
    {
        if (disposing)
        {
            // Dispose managed resources.
        }

        // There are no unmanaged resources to release, but
        // if we add them, they need to be released here.
    }
    disposed = true;

    // If it is available, make the call to the
    // base class's Dispose(Boolean) method
    base.Dispose(disposing);
}
// implements IDisposable
public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}
我在这个线程中读到的关于Dispose(bool)中的锁的内容是真的吗?它说,“元注释——同样重要的是,在非托管清理过程中永远不要获取锁或使用锁。”这是为什么?它是否也适用于非托管资源

最后,on是否曾经在不实现IDisposable的情况下实现过终结器(~MyClass()在C#中)?我相信我在某个地方读到,如果没有非托管资源,那么终结器和IDisposable是不必要的(或不可取的)。但是,在一些示例中,我确实看到了在没有IDisposable的情况下使用终结器(请参见:作为一个示例) 谢谢
Dave

这种实现
IDisposable
模式的方法是一种故障安全的方法:如果客户端忘记调用
Dispose
,运行时调用的终结器稍后将调用
Dispose(false)
(请注意,示例中缺少此部分)

在后一种情况下,即当终结器调用
Dispose
时,托管资源将已被清理,因为否则所涉及的对象将不符合垃圾收集的条件

但是如果是这样的话,GC.SuppressFinalize(这个)调用做什么呢

运行终结器会带来额外的成本。因此,如果可能的话,应该避免。调用
GC.SuppressFinalize(this)
将跳过运行终结器,因此可以更有效地对对象进行垃圾收集

一般来说,应该避免依赖终结器,因为不能保证终结器将运行。Raymond Chen在以下帖子中描述了终结器的一些问题:

…您会注意到,如果disposing为false,则不会处理托管资源。如何/何时处理

您没有将其包含在示例中,但该类型通常会有一个析构函数,该析构函数将调用
Dispose(false)
。因此,当
disposing
false
时,您“知道”您正在进行终结器调用,因此不应该*访问任何托管资源,因为它们可能已经被终结

GC终结过程只确保终结器被调用,而不是按照它们被调用的顺序

GG.SuppressFinalize(这个)调用做什么

它阻止GC将您的对象添加到终结队列,并最终调用
object.Finalize()
(即您的析构函数)。这是一种性能优化,仅此而已

按照模式的编写方式,如果您在“if(disposing)”部分中不做任何操作,它们似乎会(稍后)被处理掉

也许;这取决于类型的编写方式。
IDisposable
惯用语的一个要点是“确定性终结”,即说“我希望您的资源现在就被释放”,并使其具有某种意义。如果“忽略”
Dispose=true
块,并且不“转发”
Dispose()
调用,则会发生以下两种情况之一:

  • 如果类型具有终结器,则对象的终结器最终可能会在“以后”调用
  • 如果该类型没有终结器,则托管资源将“泄漏”,因为永远不会对其调用
    Dispose()
  • 在非托管清理过程中,永远不要获取锁或使用锁,这一点很重要?它是否也适用于非托管资源

    这是一个理智的问题——你的理智。清理代码越简单越好,最好不要从
    Dispose()
    抛出异常。使用锁可能会导致异常或死锁,这两种情况都是破坏一天的好方法。:-)

    on是否曾经在没有实现IDisposable的情况下实现过终结器(~MyClass()在C#中)


    可以,但这会被认为是糟糕的样式。

    处理对象的正常方式是调用它的
    Dispose()
    方法。这样做后,
    SuppressFinalize
    调用将对象从终结器队列中移除,使其成为一个可以轻松进行垃圾收集的常规托管对象


    只有当代码未能正确处理对象时,才会使用终结器。然后终结器调用
    Dispose(false)
    ,以便对象至少可以尝试清理非托管资源。由于对象引用的任何托管对象在此阶段可能已被垃圾收集,因此对象不应尝试清理它们。

    而应尝试通过模式了解处置,您可能希望将事情反过来,并尝试了解为什么该模式是基于CLR基础知识和IDisposable接口的预期用途以这种方式实现的。这里有一个非常好的介绍,可以回答您的所有问题(还有一些您不想问的问题)。

    上面描述的模式是雄辩地处理处置和最终确定的重叠问题

    在处置时,我们希望:

  • 处置所有一次性成员对象
  • 处置基础对象
  • 释放非托管资源
  • 最终确定时,我们希望:

  • 释放非托管资源
  • 除此之外,还有以下问题:

  • 处置时应安全呼叫m
    public class HasManagedMembers : IDisposable
    {
       /* more stuff here */
       public void Dispose()
       {
          //if really necessary, block multiple calls by storing a boolean, but generally this won't be needed.
          someMember.Dispose(); /*etc.*/
       }
    }
    
    public class HasUnmanagedResource : IDisposable
    {
      IntPtr _someRawHandle;
      /* real code using _someRawHandle*/
      private void CleanUp()
      {
         /* code to clean up the handle */
      }
      public void Dispose()
      {
         CleanUp();
         GC.SuppressFinalize(this);
      }
      ~HasUnmanagedResource()
      {
         CleanUp();
      }
    }