2012-08-08 73 views
2

在我的網站中,我使用控制器來生成圖像的縮略圖。我的代碼如下所示:鎖定檢查現有文件部分

var filePath = getThumbnailPath(); 
if (!File.Exists(filePath) 
{ 
    ... create thumbnail 
}  
return new Filestream(...) 

的問題是,如果兩個用戶請求相同的縮略圖和創建時,如果不創建我會得到異常。 如何在不引入太多開銷的情況下高效地在文件名對象上使用鎖定? Aristos的的評論後

重構的代碼:

Mutex m = new Mutex(false, originalImagePath); 
m.WaitOne(); 
try 
{ 
    if (!File.Exists(originalImagePath)) 
    { 
      ... create thumbnail 
    } 
} 
finally 
{ 
    m.ReleaseMutex(); 
} 
+1

我會使用一個隊列,並可能是一個小緩存,所以你會得到它一次,第二個請求會從緩存中得到它。 – 2012-08-08 18:25:41

+2

我使用互斥體來鎖定縮略圖的創建,我也將圖像文件名稱作爲互斥體的名稱,並且我沒有任何瓶頸。對於我的縮略圖,我保留了它(緩存)並在下一次請求中提供。 – Aristos 2012-08-08 19:11:46

+0

恥辱對我來說......互斥正是我所需要的。你可以發佈一些代碼...爲接受的答案...我相信你會爲像我這樣的其他人節省一天。 – 2012-08-08 19:55:40

回答

3

委託創建縮略圖其他服務。用戶將產生請求創建縮略圖。另一項服務將消費這個要求,並做實際工作。

什麼是服務,您可以選擇適合自己的服務。它可以是WCF服務,Windows服務,消息隊列或其他。

在ASP.NET網站中直接使用鎖定通常不是一個好主意,因爲它會引入一個瓶頸。

+0

如果我將它委派給另一個服務,並且我對同一資源有兩個請求...其中一個請求將不得不等待直到資源被創建......這將會阻止asp.net線程,直到資源可用。我錯了嗎?我想使用類似ConcurrentDictionary的東西來添加與特定資源關鍵字對應的對象的鎖定。但輸出代碼看起來非常糟糕:( – 2012-08-08 18:33:47

+0

我想我錯過了你的解決方案的全貌,你說我應該返回一個重定向到另一個服務,照顧資源?由於它是一個asp網絡請求,我需要 – 2012-08-08 18:47:53

+0

現在我明白了,我的第一印象是,我會延遲支票到另一個服務 – 2012-08-08 18:54:13

1

ASP.NET網站有一個能夠運行多個進程(例如Web農場等)的概念。 lock只在一個進程中鎖定。如果出於任何原因,你的代碼在多個進程中運行,你會回到同樣的問題。

此外,您的字典使用需要進行線程安全。它的方式是,它可以爲相同的文件名寫入多個值。

我推薦使用名爲Mutex。這允許跨進程相互排斥。互斥體的名稱可以簡單地作爲文件名。不需要字典。

向另一個服務發出網絡請求看起來像是它引入了更多的延遲到請求到你的網站。 (例如,向您的網站發送圖像請求需要向此「服務」發出輔助網絡請求以獲取圖像 - 或獲取圖像的位置)。