2011-06-01 46 views
10

而不是在同一個線程上進行清理(或啓動後臺線程並阻塞直到完成)在「背景」(IsBackground = false,因此它不會被終止提前終止)上啓動清理並立即返回。將Dispose/Close方法寫入異步是不是一個好主意?

這是一個壞主意,有多糟?這是一個好主意嗎?

+2

這是一個抽象的思想還是你有一個真正的非託管資源,需要大量的時間來拆卸(如果是這樣,它是什麼,我很感興趣)? – Lazarus 2011-06-01 12:42:25

+0

更多的抽象思想。我只是在查看一些IDisposable IO對象,並認爲「你應該嘗試異步執行所有IO,因爲上帝知道需要多長時間,等等,這是否也適用於析構函數?如果是,那麼爲什麼不讓它們在默認情況下是異步的在使用塊)?「 – 2011-06-01 12:47:46

+0

我非常確定GC在專用線程上運行,因此它實際上是併發的,即對象被標記爲收集並且您的應用程序將繼續執行。至少在客戶端配置文件中是這樣,我認爲服務器配置文件可能會阻塞GC。 – Lazarus 2011-06-01 12:56:04

回答

4

IDisposable替換與異步清理違反了Liskov Subsitution Principle,因爲人們會預期資源在調用後立即再次可用。

我想這是一些優化,因爲頻繁的分配/釋放的需要,這將意味着最終你可能只是問題轉移到等待被安置在後臺線程對象的量增加。這將導致更長時間的內存不足,需要進行一些同步,以確保這些對象的數量不會增長到天空。

就像拉撒路說的,更適當的解決方案可能是pool of reusable objects

+0

出於好奇,你可以展開Dispose方法中的異步實現如何違反LSP?我對它很陌生,我覺得我在這裏錯過了一些東西。 – Lazarus 2011-06-01 13:03:19

+0

LSP意味着實現IDisposable的每個對象應該具有相同的強語義。如果你考慮一個Stream到文件的例子,如果你關閉它,你可以在Dispose/Close之後立即打開另一個Stream到這個文件。如果Dispose是異步的,那麼情況就不是這樣,導致我認爲LSP違規。 – jdehaan 2011-06-01 13:50:28

+0

在某些情況下,異步Dispose會違反LSP。在其他情況下,它不會。異步Dispose對於可替換資源(例如GdiHandles)來說可能是安全的,在這些資源中,當某個特定的句柄被釋放時,沒有人願意關心,但是想避免放棄句柄堆積;它也可能有用的情況下,可以延遲任何嘗試使用資源的清理已被推遲到清理完成後。 – supercat 2011-06-01 19:07:49

1

你不希望這樣做的一個地方是如果你的對象持有一些其他線程可能正在等待使用的有限資源。

我很感興趣看到其他答案,因爲我認爲這是一個有趣的想法,並且在某些情況下可能是一種很好的方式來更快地向用戶返回數據。

5

我想你應該在處理你的非託管資源的時候看起來很難處理與啓動後臺線程相比。如果這是一個大量使用的過程,你會發現這產生了一個很大的開銷,如果沒有別的。

如果非託管資源的創建和銷燬非常昂貴,那麼也許您可以考慮在應用程序的整個生命週期中維護一個常見實例或實例池。

0

Dispose方法不應返回,直到其他代碼可能依賴的所有預期效果都已完成。 Dispose延遲清理任務是合理的,這樣做不會破壞其他代碼的期望。例如,連接池類的Dispose方法可能會立即將Disposed連接添加到池中而不關閉它們,並且後臺線程關閉一段時間內尚未使用的連接。如果可以打開多少個不同連接的限制,並且由於該池充滿了不適合當前請求的緩存(但目前未使用)的連接,則不能滿足請求,所以「打開」方法必須能夠加快清理池。

相關問題