程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 深入解析Close()和Dispose()的區別

深入解析Close()和Dispose()的區別

編輯:關於.NET

很多人都認為Close()方法內部會調用Dispose()方法,所以並沒有本質的區別!實際上這個看法不是很准確,對有些類來說,的確Close()和Dispose()沒有本質區別,但是對有些類來說並非如此!

首先,讓我們看看我們最常使用的SqlConnection的Close()方法和Dispose()方法的區別:

SqlConnection類的Dispose()方法是繼承於Component類的,源代碼是這樣的:

public void Dispose() {
             Dispose(true); //調用Dispose的一個帶參數的重載
             GC.SuppressFinalize(this);  //請求系統不要調用指定對象的終結器。
         }
         protected virtual void Dispose(bool disposing) {
             if (disposing) {
                 lock(this) {
                     if (site != null && site.Container != null) {
                         site.Container.Remove(this);
                     }
                     if (events != null) {
                         EventHandler handler = (EventHandler)events[EventDisposed];
                         if (handler != null) handler(this, EventArgs.Empty);
                     }
                 }
             }
         }

SqlConnection類的Close()方法在MSDN中的說明是這樣的:

關閉與數據庫的連接。這是關閉任何打開連接的首選方法。 如果 SqlConnection 超出范圍,則不會將其關閉。因此,必須通過調用 Close 或 Dispose 顯式關閉該連接。Close 和 Dispose 在功能上等效。如果連接池值Pooling 設置為 true 或 yes,則基礎連接將返回到連接池。另一方面,如果 Pooling 設置為 false 或 no,則會關閉到服務器的基礎連接。

看說明好象是Close()方法和Dispose()方法是類似的,實際上只是在關閉連接這個功能上等效,讓我們看看Close()方法的源代碼:

override public void Close() {
             IntPtr hscp;
             Bid.ScopeEnter(out hscp, "<sc.SqlConnection.Close|API> %d#" , ObjectID);
             try {
                 SqlStatistics statistics = null;
                 RuntimeHelpers.PrepareConstrainedRegions();
                 try {
#if DEBUG
                     object initialReliabilitySlotValue = Thread.GetData(TdsParser.ReliabilitySlot);
                     RuntimeHelpers.PrepareConstrainedRegions();
                     try {
                         Thread.SetData(TdsParser.ReliabilitySlot, true);
#endif //DEBUG
                         statistics = SqlStatistics.StartTimer(Statistics);
                         // The lock here is to protect against the command.cancel / connection.close
race condition
                         // The SqlInternalConnectionTds is set to OpenBusy during close, once this
happens the cast below will fail and
                         // the command will no longer be cancelable.  It might be desirable to be
able to cancel the close opperation, but this is
                         // outside of the scope of Whidbey RTM.  See (SqlCommand::Cancel) for other
lock.
                         lock (InnerConnection) {
                             InnerConnection.CloseConnection(this, ConnectionFactory);
                         }
                         // does not require GC.KeepAlive(this) because of OnStateChange
                         if (null != Statistics) {
                             ADP.TimerCurrent(out _statistics._closeTimestamp);
                         }
  #if DEBUG
                     }
                     finally {
                         Thread.SetData(TdsParser.ReliabilitySlot, initialReliabilitySlotValue);
                     }
#endif //DEBUG
                 }
                 catch (System.OutOfMemoryException e) {
                     Abort(e);
                     throw;
                 }
                 catch (System.StackOverflowException e) {
                     Abort(e);
                     throw;
                 }
                 catch (System.Threading.ThreadAbortException e) {
                     Abort(e);
                     throw;
                 }
                 finally {
                     SqlStatistics.StopTimer(statistics);
                 }
             }
             finally {
                 SqlDebugContext  sdc = _sdc;
                 _sdc = null;
                 Bid.ScopeLeave(ref hscp);
                 if (sdc != null) {
                    sdc.Dispose();
                 }
             }
         }

可以看到Close()方法並沒有調用Dispose()方法,雖然有一行sdc.Dispose();,但是這只是釋放SqlDebugContext實例,和SqlConnection.Dispose()方法沒有關系!

那麼區別在哪裡呢?

Close()方法只是關閉了連接,然後這個連接被存儲到連接池,所以在調用Close()方法以後,還是可以再通過Open()方法來打開連接的而調用Dispose()方法以後,這個連接就不能在使用了!

還有一個重要區別就是,當Close()方法並沒有調用GC.SuppressFinalize(this);,這導致的直接後果就是在垃圾回收的時候需要進行終止化操作,這會導致這個實例的“代齡”提升,從而極大的延遲這個對象的回收時間!

針對SqlConnection這個類來說,如果以後還需要使用這個連接可以使用Close()方法臨時關閉連接,如果以後不需要使用這個連接了,可以優先選用Dispose()方法來釋放資源,當然你可以使用using關鍵字來簡化這個過程,OleDbConnection類和OdbcConnection類的源代碼我沒有找到,但是應該和SqlConnection類是類似的!

讓我們在看一個我們常用的類,看看FileStream類的Close()方法和Dispose()方法有什麼區別:

FileStream類的Close()方法是繼承於Stream類的,源代碼是這樣的:

public virtual void Close()
         {
             Dispose(true);
             GC.SuppressFinalize(this);
         }

FileStream類的Dispose()方法是繼承於Stream類的,源代碼是這樣的:

public void Dispose()
         {
             Close();
         }

是一個標准的Dispose模式的實現,Close()方法調用的是帶參數的Dispose方法,然後調用GC.SuppressFinalize(this);請求系統不要調用指定對象的終結器。而Dispose()方法直接調用Close()方法!

對於FileStream類來說,Close()方法和Dispose()方法是沒有區別!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved