简体   繁体   English

在C#中,我们可以使用finalize来配置托管源吗?

[英]In c#,can we use finalize to dispose the managed source?

According to the pattern of how to use IDisposable, Microsoft suggests to use finalize to release unmanaged source. 根据如何使用IDisposable的模式,Microsoft建议使用finalize释放非托管源。 http://msdn.microsoft.com/en-us/library/system.idisposable%28v=VS.80%29.aspx http://msdn.microsoft.com/zh-cn/library/system.idisposable%28v=VS.80%29.aspx

But what will happen if we write some codes to release managed source in finalize? 但是,如果我们编写一些代码以最终发布托管源代码,将会发生什么? That is to say when the GC call finalize to release some managed source, what will happen? 也就是说,当GC调用完成以释放某些托管源时,将发生什么?

It's a bad practice in general . 一般来说,这是一个坏习惯。 In finalizer code you can't rely on state of you object and its managed resources - they can be collected or disposed/finalized already. 在终结器代码中,您不能依赖于对象状态及其托管资源-它们可以被收集或处置/确定。 Also, you can't rely on order, in which CLR calls Finalize . 另外,您不能依赖于CLR调用Finalize顺序。

In general, using Finalize to clean up an outside managed resource is useless and may be dangerous. 通常,使用Finalize清理外部托管资源是没有用的,并且可能很危险。 When an object finalizer runs, managed resources it holds are likely either: 当对象终结器运行时,它拥有的托管资源可能是:

  1. Cleaned up already as a consequence of having had their finalizers run, in which case disposing them will be useless. 由于运行了终结器,因此已经进行了清理,在这种情况下,处理它们将毫无用处。
  2. Not yet cleaned up, but recognized as being unreferenced by any live objects, in which case their finalizer will run in due course whether or not the currently-executing finalizer tries to clean them up. 尚未清理,但被识别为未被任何活动对象引用,在这种情况下,无论当前执行的终结器是否尝试清理它们,终结器都将在适当的时候运行。
  3. Still in use by other live objects, in which case they should not be cleaned up by the presently-running finalizer. 其他活动对象仍在使用它们,在这种情况下,当前正在运行的终结器不应清除它们。

There are some situations where it may be helpful to have finalizers call cleanup code on other managed objects, but such invocation is generally only appropriate in cases where objects know about each others' internal details, and should generally be performed either using protected or internal methods, or using privately-exchanged delegates. 在某些情况下,让终结器在其他托管对象上调用清除代码可能会有所帮助,但是这种调用通常仅在对象知道彼此内部细节的情况下才适用,并且通常应使用protectedinternal方法来执行,或使用私人交流的代表。 In some cases, for example, there may be two or more objects which know about each other, and have finalizers that must run in a particular order. 例如,在某些情况下,可能有两个或更多彼此了解的对象,并且这些对象必须以特定顺序运行。

As an example, there may be one class whose purpose is to send data to a USB device, and another class whose purpose is to control a piece of equipment connected to that device. 例如,可能有一个类别的目的是向USB设备发送数据,而另一个类别的目的是控制与该设备连接的设备。 If the latter class wants to make certain the equipment receives a "shutdown" command, it may be necessary that its finalizer send the command before the USB-connection class finalizer closes the connection. 如果后一类希望确定设备接收到“关闭”命令,则可能有必要在USB连接类终结器关闭连接之前,其终结器发送该命令。 The cleanest way to handle this may be to have the constructor of the USB-connection object accept a callback which it will invoke from its finalizer. 解决此问题的最干净的方法可能是让USB连接对象的构造函数接受一个回调,该回调将从其终结器调用。 If the class has no such feature, things can be rather icky. 如果该类没有这种功能,那么事情可能会变得很棘手。 Another approach may be to have an object separate from the wrapper which holds all the information necessary for cleanup, along with a WeakReference to the wrapper object and has a timer-tick event which will perform cleanup if the WeakReference is dead. 另一种方法可能是使一个与包装器分离的对象,该对象保存清理所需的所有信息,以及对包装器对象的WeakReference ,并具有一个定时滴答事件,如果WeakReference失效,它将执行清除。 If the timer is bound to the thread on which the wrapper object is created, that may allow cleanup to be performed even if the wrapper object is abandoned, provided the thread is still alive (if it may not be, things get more complicated). 如果将计时器绑定到在其上创建包装对象的线程,则即使该包装对象被放弃,也可以允许执行清除操作,前提是该线程仍处于活动状态(如果不是,则情况会更加复杂)。

Why (or better, how) would you release something that is managed in a finalizer? 为什么(或者更好,如何)发布由终结器管理的内容? Everything the current object owns is already seen as garbage at this point and will be collected in the next run of the garbage collector. 目前,当前对象拥有的所有内容都已被视为垃圾,并将在下一次垃圾收集器中收集。 And everything the current does not own can't be released since something else might still reference it. 所有的一切都目前拥有不能被释放,因为别的东西可能仍然引用它。

There is no need to write Dispose/ Finalize for Managed code. 无需编写针对托管代码的处置/完成。 bcz it will deleted by CLR when the object is no more referenced. bcz当不再引用该对象时,它将被CLR删除。 Dispose methods are write for unmanaged code like file handler or database commands. 处理方法是针对非托管代码(例如文件处理程序或数据库命令)编写的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM