2013-06-20 44 views
-1

我處於清理非託管資源的關鍵部分。爲了解決這個問題,我改變了這個...我需要使用語句來鎖定處理資源,我的自定義解決方案是否健壯?

void SomeMethod() 
{ 
    //work 
    using (var doc = SpreadsheetDocument.Open(results.FileName, true)) 
    { 
     //use doc. 
    } 
} 

這個...

public static readonly object Locker = new object(); 
void SomeMethod() 
{ 
    //work 
    {//scoping doc 
     var doc = SpreadsheetDocument.Open(results.FileName, true); 
     try 
     { 
      //use doc 
      //At some point wrapping a critical section via lock(Locker) 
     } 
     finally 
     { 
      lock (Locker) 
      { 
       if (doc != null) ((IDisposable)doc).Dispose(); 
      } 
     } 
    } 
} 

其中,我相信,是一個醜陋的和脆弱的解決方案。所以,我將其更改爲以下...

public static readonly object Locker = new object(); 
void SomeMethod() 
{ 
    //work 
    CustomUsingWithLocker(SpreadsheetDocument.Open(results.FileName, true), Locker, doc => 
    { 
     //use doc 
     //At some point wrapping a critical section via lock(Locker) 
    }); 
} 

public static void CustomUsingWithLocker<T>(T resource, object locker, Action<T> body) 
    where T : class, IDisposable 
{ 
    try 
    { 
     body(resource); 
    } 
    finally 
    { 
     lock (locker) 
     { 
      if (resource != null) resource.Dispose(); 
     } 
    } 
} 

此定製解決方案是否健壯?我可以改進嗎?是否保證釋放任何非託管資源,如使用內置語句?

+0

爲什麼在保護文檔不是共享對象時使用鎖定? – Polyfun

+0

在我的customUserWithLocker裏面,doc用於創建一個excel文檔。如果在此期間有不同的文檔正在處理,則會引發超時異常。通過鎖定excel文檔的創建並鎖定dispose調用,超時期望從不會發生。我相信文件流在文檔之間共享。 – Onosa

+0

從ASP.NET或其他服務器技術使用Office Interop是一個糟糕的主意。這些API被編寫用於桌面應用程序,用於自動化Office(一套桌面應用程序)。服務器應用程序在許多方面有所不同,因此在其中使用Office Interop是非常非常糟糕的主意。它也不受Microsoft的支持,並可能違反您的Office許可證。請參閱[服務器端自動化辦公室的注意事項](http://support.microsoft.com/kb/257757) –

回答

0

這裏的前提似乎是Dispose被多個線程調用多次。如果是這樣的話,改變這個前提。即使doc被傳遞到...在另一個線程中使用的地方,那個地方也不會負責處理它,並且不應該處置它。找到它在using末尾以外的位置,並將其更改爲不這樣做。

如果Dispose沒有被其他地方調用,你只需有一個非線程安全的Dispose方法不應從多個線程訪問(即使你的代碼目前是足夠聰明,那麼做)和你只是試圖應用良好的防禦性編程,我認爲可以肯定地說這不是必要的。在這個特定的上下文中,這個方法是一個有效的約束,說只有一個線程應該負責處理這個對象。

+0

我相信'Dispose'只能在'finally'部分調用一次。如果一個文檔處於關鍵部分(特別是創建Excel文檔時),並且另一個文檔正在處理,則拋出異常。當我用某種共同的互斥包裹關鍵部分和處置時,我沒有例外。所以,我相信你是對的,因爲'Dispose'不是線程安全的。我認爲文檔共享文件流(很差)。 總體流程由一個'SemaphoreSlim(2)'封裝,並且在處理過程中創建一個文檔,所以這就是爲什麼它們經常發生衝突。 – Onosa

相關問題