如何确保对象在.NET中得到正确处理?我使用连续运行的C#在.NET2中创建了一个Windows窗体应用程序。我对大多数帐户都很好,但据报道偶尔会失败。我能够在50%的时间内监控它的性能,我从未注意到故障。在这一点上,我担心该程序可能使用了太多资源并且在不再需要时没有处理它们。正确处理已创建计时器和图形路径、SQL连接等图形对象的对象的创建的最佳做法是什么?或者我可以依靠dispose方法来处理所有垃圾收集吗?另外:有没有办法可以监视应用程序使用的资源?最佳做法是确保在不再需要对象时调用实现IDisposable接口的所有对象。这可以使用using关键字或try/finally结构来完成。在为表单生命周期分配资源的WinForms表单中,需要一种稍微不同的方法。由于窗体本身实现了IDisposable,这表明在某个时刻将在此窗体上调用Dispose。您希望确保您所支配的资源得到并发处理。为此,您应该覆盖表单Dispose(booldisposing)方法。实现应如下所示:protectedoverridevoidDispose(booldisposing){if(disposing){//在此处处置托管资源}//在此处处置非托管资源}关于表单中组件的注释:如果对象实现IComponent接口,它可以将实例放入表单容器中。当容器本身被丢弃时,容器将负责处理组件。除了已经说过的内容之外,如果您正在使用COM组件,那么确保它们已完全发布是一个非常好的主意。我有一个用于COM版本的片段:privatevoidReleaseCOMObject(objecto){Int32countDown=1;while(countDown>0)countDown=System.Runtime.InteropServices.Marshal.ReleaseCOMObject(o);您应该在稀缺资源上调用Dispose以释放它们。您可以使用using语句:using(varresource=newMyScarceObject()){//此处将使用资源...}//将通过自动调用Dispose释放资源有多种方法可以确保这一点。我发现的主要帮助是“using”关键字。这适用于:using(SqlConnectionconnection=newSqlConnection(myConnectionString)){/*在此处使用连接*/}这基本上转化为:SqlConnectionconnection=null;尝试{connection=newSqlConnection(myConnectionString);}finally{if(connection!=null)connection.Dispose();所以它只适用于实现IDisposable的类型。在处理钢笔和画笔等GDI对象时,此关键字很有用。但是,在某些情况下,您需要保留比方法当前作用域更长的资源。通常,如果可能最好避免这种情况,但例如在处理SqlCe时,保持一个连接打开到数据库连接会提高性能。因此,无法避免这种需要。在这种情况下您不能使用“使用”,但您仍然希望能够轻松回收连接所拥有的资源。您可以使用两种机制来获取这些资源。一种是通过终结者。所有超出范围的托管对象最终都会被垃圾收集器收集。如果定义了终结器,GC将在收集对象时调用此方法。publicclassMyClassThatHoldsResources{privateBrushmyBrush;//这是一个终结器~MyClassThatHoldsResources(){if(myBrush!=null)myBrush.Dispose();但是上面的代码是可悲的。原因是因为在完成时您无法保证哪些托管对象已被收集,哪些尚未收集。上面示例中的“myBrush”可能已被垃圾收集器丢弃。因此,最好使用finaliser来收集托管对象,其目的是组织非托管资源。Terminator的另一个问题是它不是确定性的。比方说,我有一个通过串行端口进行通信的类。一次只能打开一个到串行端口的连接。因此,如果我有以下课程:classMySerialPortAccessor{privateSerialPortm_Port;publicMySerialPortAccessor(stringport){m_Port=newSerialPort(port);m_Port.Open();}~MySerialPortAccessor(){if(m_Port!=null)m_Port.Dispose();然后,如果我使用这样的对象:publicstaticvoidMain(){Test1();测试2();}privatestaticvoidTest1(){MySerialPortAccessorport=newMySerialPortAccessor("COM1:");//做事}privatestaticvoidTest2(){MySerialPortAccessorport=newMySerialPortAccessor("COM1:");//做事}我有一个问题。问题是终止符不是确定性的。那就是我不能保证它什么时候运行并因此处理我的串行端口对象。所以当我运行测试2时,我可能会发现端口仍然是打开的。虽然我可以在Test1()和Test2()之间调用GC.Collect()来解决这个问题,但不推荐这样做。如果您希望收集器发挥最佳性能,就让它发挥作用。所以我真正想做的是:classMySerialPortAccessor:IDispable{privateSerialPortm_Port;publicMySerialPortAccessor(stringport){m_Port=newSerialPort(port);m_Port.Open();}publicvoidDispose(){if(m_Port!=null)m_Port.Dispose();我会这样重写我的测试:publicstaticvoidMain(){Test1();测试2();}privatestaticvoidTest1(){using(MySerialPortAccessorport=newMySerialPortAccessor("COM1:")){//dostuff}}privatestaticvoidTest2(){using(MySerialPortAccessorport=newMySerialPortAccessor("COM1:")){//dostuff}}现在这行得通了。终结者呢?为什么要使用它?非托管资源的可能实现并且不调用Dispose。作为他人使用的组件库的作者;他们的代码可能忘记处理该对象。其他东西可能会终止这个过程,所以.Dispose()不会发生。由于这些情况,应实施终结器以清理任何非托管资源作为“最坏情况”的情况,但Dispose还应清理这些资源,以便您可以进行“确定性清理”例程。所以,最终,.NETFrameworkGuidelines书中推荐的模式实现如下:publicvoidSomeResourceHoggingClass,IDisposable{~SomeResourceHoggingClass(){Dispose(false);}publicvoidDispose(){Dispose(true);}//virtual所以子类可以覆盖它并添加自己的东西//protectedvirtualvoidDispose(booldeterministicDispose){//我们可以整理托管对象if(deterministicDispose){someManagedObject.Parent.Dispose();一些ManagedObject.Dispose();}DisposeUnmanagedResources();//如果我们已经被.Dispose()处理掉//那么我们可以告诉GC它不需要//结束这个对象(这样可以节省一些时间)//GC.SuppressFinalize(this);}}一些提示:-尽可能利用Using()关键字。如果您有单元测试,我建议重构您的代码以实施此更改。http://msdn.microsoft.com/en-us/library/yh598w02.aspx-请记住在整个应用程序期间显式注销所有事件处理程序并从列表中删除所有对象。这是程序员在.NET中最常犯的错误,它会阻止收集这些项目。至于监控内置的perfmon(2)是否可以正常使用内存等。如果您担心文件句柄、dll句柄等。我推荐ProcessExplorer和ProcessMonitorObject。当对象不可访问时将调用Finalize方法。在实现IDisposable的类中禁止此类不必要的调用很有帮助。你可以通过调用GC.SuppressFinalize方法来做到这一点以上是C#学习教程:如何确保对象在.NET中被正确处置?如果分享的内容对你有用,需要了解更多C#学习教程,希望你多多关注——publicvoidDispose(){//在这里释放资源GC.SuppressFinalize(this);}本文来自网络合集,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
