2012-02-07 54 views
4

我在Web服務中實例化了一個類,該服務在靜態成員中持有某些資源。如果我不是靜態地堅持這些資源,我可能會通過一些IDisposable對象訪問它們,我可以在Dispose上釋放這些資源。不管是否堅持這個會話是一個好主意,當靜態解構類型時,.NET是否提供了任何方式來調用任何清理代碼?Static Deconstructor

請不要回答這個問題與任何「停止控制靜態成員變量資源」的問題。我理解靜態持有這些信息的缺點,並願意接受後果(我們正在使用它將處理時間從58小時減少到4小時,以進行一些批處理)。具體問題是:鑑於這種情況,有沒有好的方法來清理這些資源?

編輯: 我知道這個類將繼續存在於其餘的過程中,但是對於靜態構造函數,當您將該類型加載到內存中時,.NET爲您提供了一些機會。你可以在另一端做任何事嗎?

+10

什麼時候將靜態類型解構? – haiyyu 2012-02-07 19:16:08

+0

@haiyyu - 這是一個很好的問題,我不知道。 – LJM 2012-02-07 19:17:19

+3

這聽起來像你*不*真正理解使用這樣的靜態變量的缺點,因爲缺點之一是「他們的一生是AppDomain的生命週期」......我會調查你是否可以將其綁定到Web服務生命週期的一部分,仍然避免靜態成員。 – 2012-02-07 19:22:25

回答

3

實際上沒有辦法從託管代碼執行此操作。你想要的是處理你的裝配被卸載,但是在大多數情況下,當你想要的時候不會發生這種情況。

的詳細信息:

有一個AppDomain.DomainUnload事件(http://msdn.microsoft.com/en-us/library/system.appdomain.domainunload.aspx)你可以處理。這可以在您的應用程序域從其託管過程(例如ASP.NET)卸載時處理。

但是,如果你是一個EXE,或者主機EXE正在被回收,這將不會被提出。如果設置正確,您可能能夠處理本機DLL_PROCESS_DETACH並將其反彈回託管代碼,但由於加載程序鎖定,您必須非常小心在該上下文中執行的操作(觸發程序集加載的任何操作僵局)。

你可以閱讀這對於上報應什麼清理一些見解(提示:不要太多):http://blogs.msdn.com/b/oldnewthing/archive/2012/01/05/10253268.aspx

基本上,你需要擔心的是刷新緩衝區寫入磁盤,如果你需要做的唯一的事情更復雜的東西,你已經搞砸了。 malloc(),因此new()可能會立即崩潰你的程序。這也適用於託管代碼。

3

這個問題並沒有什麼意義,在進程的整個生命週期中靜態的生命,當一個進程結束時,所有的東西都被OS清除。如果進程不再運行,進程無法繼續使用資源。

+0

我試圖概括這個問題太多。在這個特定的情況下,我們有一個會議在其他地方開放。能夠關閉該會話將很高興。 – LJM 2012-02-07 19:18:31

+2

我想你需要問一個更具體的問題與你的應用程序的細節。例如,asp.net有一個'application_end'方法,它允許你在過程結束或重啓時執行這種類型的事情。但是對於Windows服務,答案會有所不同。 – 2012-02-07 19:21:18

1

你不能破壞沒有實例化的東西。

我認爲你應該使用Singleton模式而不是靜態地保存所有的數據。

+0

通過這種邏輯,你可以說你不能「構造」一些靜態的東西,但那是不真實的。我們有靜態構造函數。 – LJM 2012-02-07 19:32:12

+0

假設我們有一個類名爲Foo的靜態構造函數。當它是靜態構造函數正在調用時,我們沒有在該構造函數中實例化任何Foo對象。靜態構造函數只初始化類而不是該類中的對象。 – 2012-02-07 20:28:21

+0

是的,我知道...... – LJM 2012-02-07 20:44:25

2

什麼時候最後一點這個靜態會變得很重要?在這一刻,你應該破壞它。

Destruct可能意味着像「釋放一些非託管內存,寫出緩存到數據庫並將靜態變量設置爲空」。

訪問的最後一點在不同的應用程序中意味着不同的事物。在ASP.NET應用程序中,您無法可靠地確定這一點。它來自Application_End事件或AppDomain.Unload事件觸發時,以先到者爲準。在WCF中也是一樣。在WinForms應用程序中,您可以在主窗體關閉後或在主應用程序的最後一行之後使用它。

無論如何,你需要自己清理。

替代方法:您可以將狀態封裝到可終結對象中。它將在AppDomain卸載時清除。如果你寫一個所謂的關鍵終結器,你幾乎可以保證你的清理將會執行。

+0

我剛剛添加了一個實用的替代方案。 – usr 2012-02-07 19:34:33

-1

如果您正在存儲爲靜態成員的對象正確實現了IDisposable,那麼.net運行時應該在應用程序卸載時處理任何資源。如果任何對象不這樣做,那麼我建議你創建實現IDisposable的包裝類,以便你可以自己清理。

IDisposable on MSDN

+0

你有什麼我可以參考來證實這一點?我想更好地理解它是如何工作的。 – LJM 2012-02-07 19:43:32

+0

我不知道任何有關你的確切情況的參考資料,除了MSDN中的IDisposable文檔(這解釋得非常好 - 鏈接添加到答案)。如果你創建一個包裝類,你可以附加你的調試器,然後卸載該過程,看看會發生什麼。您應該可以在Dispose方法中設置斷點,或者寫入日誌或其他東西以證明它已被調用。 – Ray 2012-02-07 20:02:36