2012-11-01 40 views
2

問題我有以下代碼讀取文件與StreamReader的,ThreadSafety和讀取模式

StreamReader str = new StreamReader(File.Open(fileName, FileMode.Open, FileAccess.Read)); 
string fichier = str.ReadToEnd(); 
str.Close(); 

這是一個asp.net web服務的一部分,並在生產中一直在努力罰款的一年了。現在隨着服務器負載的增加,客戶已經開始變得「​​文件已被使用」錯誤。該文件正在從該代碼讀取,並且從不寫入應用程序。

我清楚地看到的一個問題是我們沒有緩存文件的內容以供將來使用。我們會這樣做。但我需要明白爲什麼以及如何解決這個問題。

是否因爲多個線程試圖讀取文件?我讀到StreamReader不是線程安全的,但爲什麼當我在Read模式下打開文件時它會成爲問題?

回答

3

您需要打開允許讀訪問的文件。使用File.Open這個超載來指定文件共享模式。您可以使用FileShare.Read來允許讀取此文件。

Anothr可能的解決方案是將該文件一次加載到內存中的類的靜態構造函數中,然後將內容存儲在靜態只讀變量中。由於靜態構造函數保證只運行一次並且是線程安全的,因此您無需執行任何特殊的操作就可以使其工作。

如果您永遠不會更改內存中的內容,您訪問數據時甚至不需要鎖定。如果您更改了內容,則需要先在每次要更改時都克隆這些數據,但是再次,由於實際原始數據不會更改,因此不需要鎖定克隆操作。

例如:

public static class FileData 
{ 
    private static readonly string s_sFileData; 

    static FileData() 
    { 
     s_sFileData = ...; // read file data here using your code 
    } 

    public static string Contents 
    { 
     get 
     { 
      return (string.Copy (s_sFileData)); 
     } 
    } 
} 

此封裝你的數據,讓您只讀訪問。

如果您的代碼可能會修改文件內容,您只需要String.Copy() - 這只是一種強制創建新字符串實例以保護原始字符串的預防措施。由於string是不可變的,所以只有當你的代碼使用字符串指針時才需要 - 我只添加了這一點,因爲我剛剛在我自己的代碼中遇到了類似變量的問題,上個星期我使用指向緩存數據的指針。 :)

1

FileMode只是控制你可以做什麼(讀/寫)。

共享訪問的文件,在操作系統級別的處理,您可以要求行爲與文件共享(第三個參數),見doc