2012-02-01 18 views
3
public class SimpleLogger 
{ 
    static readonly string logFile = ConfigurationManager.AppSettings["LogFile"]; 

    static StreamWriter GetStream() 
    { 
     return File.Exists(logFile) ? 
      File.AppendText(logFile) : File.CreateText(logFile); 
    } 

    public static void Write(string msg) 
    { 
     using (var sw = GetStream()) 
     { 
      sw.Write(msg); 
     } 
    } 
} 

上述代碼因使用不當而無法正確關閉/處置流。隨後的寫入給出了'使用中的文件'IOException。管理靜態方法中的一次性物體

如果該類被修改爲使用非靜態方法,它似乎工作正常。

我不明白爲什麼會有行爲上的差異?

回答

7

處置是好的; GetStream提供一個開放的作家; Write關閉/處置它 - 排序。但是如果我必須猜測,問題是併發的使用 - 即多線程(特別是在web應用程序中)在同一時間訪問文件。如果是這樣的話,選擇:

  • 使Write(以及任何其他訪問文件)同步,因此只有一個調用者可以可能嘗試有文件同時打開
  • 使用預罐裝日誌框架,將已經處理這種情況(這裏常用的方法包括同步,也:在本地緩存中的數據,然後向下定期推送數據 - 避免了一遍又一遍又一遍地打開文件)

在特定;你唯一的靜態是文件路徑本身。因此,將它用作靜態方法和實例方法之間沒有明顯的區別。

作爲一個附註,File.AppendAllText可能在這裏很有用,但並不能避免併發問題。

+0

那麼,你是否說我改變它使用非靜態方法時似乎工作的唯一原因是因爲我在測試它時得到了'幸運'? – fearofawhackplanet 2012-02-01 14:42:50

+0

@fearofa - 看起來像,你有能力測試。將一個睡眠(10)放入靜態版本。 – 2012-02-01 15:16:01

3

我不認爲從靜態變爲實例可以解決問題,因爲它們最終都在爭奪靜態資源(文件)。 This答案可能會對你有幫助。或許,如果你離開了這兩種方法靜態和聲明的靜態同步對象調用線程使用(因爲資源是靜態的本身)將有助於鎖定?例如:

private static object _objectLock = new object(); 

同步從多個線程訪問該文件,因此:

public static void Write(string msg)  
{   
    lock(_objectLock) 
    { 
     using (var sw = GetStream())   
     {    
      sw.Write(msg);   
     } 
    }  
}