2011-01-26 16 views
10

come un esercizio di curiosità più che altro, si consideri la seguente semplice classe di registrazione:NET 2.0: File.AppendAllText (...) - thread-safe implementazione

internal static class Logging 
{ 
    private static object threadlock; 

    static Logging() 
    { 
     threadlock = new object(); 
    } 

    internal static void WriteLog(string message) 
    { 
     try 
     { 
      lock (threadlock) 
      { 
       File.AppendAllText(@"C:\logfile.log", message); 
      } 
     } 
     catch 
     { 
      ...handle logging errors... 
     } 
    } 
} 

È il lock bisognosi in tutto File.AppendAllText(...) o il metodo è intrinsecamente thread-safe dalla sua stessa implementazione?

La ricerca di informazioni su questo produce molte informazioni contraddittorie, alcuni dicono di sì, altri dicono di no. MSDN non dice nulla.

risposta

16

File.AppendAllText acquisirà un blocco di scrittura esclusivo sul file di registro, il che causerebbe l'eventuale eccezione di thread concorrenti che tentano di accedere al file. Quindi sì, è necessario un oggetto di blocco statico per impedire a più thread di provare a scrivere sul file di registro contemporaneamente e sollevando uno IOException.

Se si tratta di un problema, suggerirei di accedere a una tabella di database che svolgerà un lavoro migliore di gestione di scrittori di registri simultanei.

In alternativa, è possibile utilizzare TextWriterTraceListener che è thread-safe (beh, sta andando a fare il blocco per voi, preferisco scrivere il mio codice multithread il più possibile).

+1

Questo è contraddittorio. Se File.AppendAllText ha un blocco di scrittura esclusivo, perché è necessario un blocco separato? – iheanyi

+4

Hai frainteso, è il file che è bloccato per la scrittura. Quindi qualsiasi altro thread che tenta di scrivere allo stesso tempo riceverà un'eccezione. Per evitare ciò, è necessario serializzare le scritture utilizzando un blocco nel programma. – Pradeep

+0

Non sprecare le preziose risorse del database per la registrazione se si utilizza un database relazionale pesante, altrimenti se si utilizza un database lite nosql, non è male accedere al database. Utilizzare qualcosa come il registro eventi di Windows se si desidera effettuare il login localmente, ma non scrivere direttamente sul file system. Ma perché non scrivere un nuovo file per log piuttosto che append se hai bisogno di essere thread safe e non-blocking? –

0

È thread-safe, nel senso che apre il file con la condivisione di lettura, quindi supponendo che il proprio file system rispetti i blocchi di file, solo un thread potrà scrivere sul file alla volta. Altri thread possono, tuttavia, ottenere letture sporche se stanno tentando di leggere lo stesso file.

+7

E altri thread generano eccezioni durante il tentativo di scrittura. –

0

Il test delle scritture parallele mostra che si otterrebbe un System.IO.IOException se si dovesse commentare la propria istruzione di blocco.