2015-03-02 205 views
0

我有像這樣C#靜態對象引用

public class FileLogger 
{ 
    public FileLogger(string typeOfLog) 
    { 
    //implementation 
    } 

    public void LogError(string err) 
    { 
    //implementation 
    } 

    public void LogMessage(string err) 
    { 
    //implementation 
    } 
} 

一類由於這是記錄其輸出到文件的應用程序日誌類,一個本來期望它是一個靜態類。但是,你可以看到它不是。然而,它在這樣的應用中使用:

多線程由BugetApplication類的分類方法啓動。該類中的任何錯誤都會觸發在BugetApplication類的clsf_handleEvent方法中處理的事件。所以多個線程可以分別觸發自己的事件。將創建實例變量作爲BugetApplication類中的靜態變量在這裏有什麼作用,或者保持它不靜態具有相同的效果?我不希望任何一個線程覆蓋另一個線程的錯誤信息。

編輯 只是爲了清楚的事情,只會創建一次的BugetApplication類有一個靜態變量'靜態FileLogger記錄器; '它在構造函數中創建一個實例,並將一些值傳遞給FileLogger類的構造函數。在BugetApplication類中,有一個方法調用Classification類的分類方法。 Classify方法啓動各種線程,並在出現任何錯誤時觸發BugetApplication類中處理的事件,以便此clsf_handleEvent方法可對其進行多次調用。

+0

如果您需要線程同步,那麼它是否爲'靜態' – Spo1ler 2015-03-02 10:53:13

+0

感謝您使用'public BugetApplicationClass()'創建每個BugetApplication實例的新記錄器實例。你的意思是'靜態BugetApplicationClass()' - 只被調用一次的靜態ctor? – 2015-03-02 10:54:34

+0

單身人士如何確保日誌和記錄器的一個剪切實例? – 2015-03-02 11:06:56

回答

2

爲什麼你認爲它會覆蓋另一個線程的錯誤信息?記錄器應該只是追加消息,所以不應該有任何覆蓋(取決於你如何處理日誌記錄)。但是有一個潛在的問題 - 根據您的日誌記錄功能,您可能會阻止對文件的訪問。由於該方法適用於外部文件,因此您應該在函數中使用lock

真的沒關係,如果類是靜態的或不是,問題是併發訪問外部資源需要同步多個線程成爲線程安全。

lock documentation on msdn

+0

我在FileLogger類中使用log4net並調用其方法。哪個函數應該有鎖,什麼應該被鎖定? – user20358 2015-03-02 11:23:02

+1

log4net是線程安全的,所以你的代碼應該是現狀(除非你做了一些時髦)。如果您沒有使用線程安全庫,則必須在打開文件並寫入文件的記錄器中鎖定該部分 – walther 2015-03-02 11:26:45

1

這真的取決於實際執行記錄的。當他們使單元測試變得更加困難時,靜態類現在不被接受。許多常規以靜態或單件(記錄器,電子郵件等)實現的設施現在提供了單元測試/ IoC友好的替代方案(例如工廠和界面或虛擬類)。

這些設施的設計通常是客戶端應用程序用於交互的前端類和負責同步和實際日誌記錄(或電子郵件或其他)的異步後端。

問題的關鍵是前端是否是多線程的。

如果它們不是;你應該爲每個線程創建一個新的。在這種情況下,記錄器可能必須是使用它的方法的局部變量或參數。

但是,它們通常是多線程和可重入的,因爲它們所做的只是將日誌消息傳遞到後端並且沒有自己的狀態。在這種情況下,它們可以保存爲靜態變量或應用程序範圍的單例,但最好將它們作爲單例在IoC容器中實例化並將它們注入到使用它們的類中。這樣做使得使用模擬記錄器編寫單元測試變得容易很多。