熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> .NET編程 >> 正文

.NET 語言的 using statement 與資源釋

2013-11-12 23:38:30  來源: .NET編程 
NET x 的 C#NET 的各種語言中有所謂的 using statement (如本 blog 上一篇帖子「使用ADONET 的NextResult 方法取得多個Result Set」的代碼范例)可保證自動 dispose (釋放) unmanaged object (對象) 所占用的資源包括因未處理的 exception 而造成區塊結束 (但 StackOverflowException 除外)系統都會 dispose 資源因此若您在 using 區塊中建立了數據庫的 connection即無須再手動 close connection亦無須再下 ConnectionDispose()CommandDispose() 等指令根據 MSDN Library 和目前市面上幾本 ADONET 原文書都有提到在 using 區塊中會自動去做 dispose 的動作NET 的 garbage collector 會自動釋放不再使用的 managed resources 所占用的內存不用程序員手動撰碼但 unmanaged resources 則需要程序員自行下 Dispose() 去做處理以讓對象徹底終止 unmanaged resources 的使用例如傳統的做法常會在 trycatchfinally pattern 中去呼叫 Dispose 方法但若是數據庫的聯機則必須有不同考慮因為若任意下 Dispose 提早回收也可能導致聯機無法有效地被重復引用
 
  現在大部分的數據庫和 Data Provider 都有支持 Connection Pooling 機制亦即在建立完數據庫的聯機後當程序員呼叫 Close 方法關閉一個數據庫的 Connection 對象時NET 的 Data Provider 並不會將這個對象所占用的內存空間釋放掉而是將此對象暫存至 Pool 之中 以便待會可以再重復使用
 
  若在設定時間 (默認為 秒) 內沒有應用程序使用到此對象或是呼叫了 Dispose 方法NET Data Provider 才會真正關閉這個聯機並由 Garbage Collector 自動將資源收回因此常有 web 程序員在網絡上各討論區提到是否有必要在呼叫 Close 方法後再呼叫 Dispose 方法並將 Connection 設為 Nothing (或 Null)?答案是不必要的因為 GC 過一陣子就會自動回收未再被參照的聯機手動呼叫 Dispose 只不過提早回收的動作而已而且若是該聯機可能會在短時間內被大量使用者同時存取的話也應讓其待在 Pool 中待命而應避免手動呼叫 Dispose 方法導致它被真正關閉並被回收而無法有效地被重復使用
 
  由於 GC 只會在系統閒置或內存不足時才啟動因此除非是使用頻率非常繁復的資源否則交由 GC 自行處理即可而設為 Nothing (或 Null) 也只是將 Connection 變量的位置清除 (Null Reference)事實上原來 New 出來的 Connection 對象還是存在而 Dispose 方法是用來處理自行建立的 Windows 資源但又不會自行釋放的對象如檔案 (開檔與關文件)GDI 對象 (直接由 Win API 叫用)…等等
 
  接下來再回頭探討 NET 的 VB/C# 語言中都有的 using statementusing 語句算是簡易版的 tryfinally pattern可讓程序員以較簡便的寫法盡早去釋放資源尤其最適用在有限的 unmanaged resources 上例如檔案和串流 I/OSocket 網絡連接File Handle (檔案控制代碼)COM 組件繪圖和字形數據庫存取WorkflowRuntime (WF)…等等的內存自動釋放using statement 遇到例外時也會拋出例外 (throw)但不會去 catch 處理例外因此若您想要自行處理例外的話只能回歸傳統的 trycatchfinally 寫法
 
  提供給 using statement 的對象必須實作 IDisposable 接口若是自己寫的 class只要實作 SystemIDisposable 接口即擁有 Dispose 方法之後若引用 using statement 去釋放這個 class 的 instance即會自動做 object 的 Close()Dispose()設定為 null (Nothing) 這三種動作不需要再自己手動處理反而若是自己手動多下一次 Close()會讓 CLR 浪費資源多做一次處理反倒會影響程序「性能 (performance)」根據國外網站及 ADONET 書籍證實若 using 語句搭配 CommandBehaviorCloseConnection 一起使用其重復關閉數據庫聯機的動作會大幅地降低程序性能處理時間甚至會多出 % 以上 (叫用 ExecuteReader() 時若搭配 CommandBehavior 枚舉值 (enumerated value)可要求在查詢完成後自動關閉數據庫聯機)
 
  此外using statement 也可多層巢狀地使用例如第一層的 using statement 裡包 SqlConnection 的宣告及 instance 的新增第二層包 SqlCommand第三層包 SqlDataReader您亦可在巢狀的 using statement 中指定多種的系統資源包括數據庫的 transaction 交易處理
From:http://tw.wingwit.com/Article/program/net/201311/11179.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.