Frage
Kann File.AppendAllText
Kollisionen von mehreren Schreibern verwalten?Behandelt File.AppendAllText Kollisionen (d. H. Mehrbenutzer-Parallelität)?
Forschung
Ich bemerkte, dass die MSDN documentation nicht wirklich eine Position oder so schaffen, so dass ich beschloss ich, den Code reflektieren würde und nur sehen, was es tut. Im Folgenden finden Sie die aufgerufene Methode von File.AppendAllText
:
private static void InternalAppendAllText(string path, string contents, Encoding encoding)
{
using (StreamWriter streamWriter = new StreamWriter(path, true, encoding))
{
streamWriter.Write(contents);
}
}
und wie Sie sehen können nutzt es einfach eine StreamWriter
. Also, wenn wir ein wenig tiefer in die graben, speziell den Konstruktor es verwendet, so finden wir, dass es letztlich dieser Konstruktor ruft:
internal StreamWriter(string path, bool append, Encoding encoding, int bufferSize, bool checkHost) : base(null)
{
if (path == null)
{
throw new ArgumentNullException("path");
}
if (encoding == null)
{
throw new ArgumentNullException("encoding");
}
if (path.Length == 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath"));
}
if (bufferSize <= 0)
{
throw new ArgumentOutOfRangeException("bufferSize", Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum"));
}
Stream streamArg = StreamWriter.CreateFile(path, append, checkHost);
this.Init(streamArg, encoding, bufferSize, false);
}
mit den folgenden Werten:
path: the path to the file
append: the text to append
encoding: UTF8NoBOM
bufferSize: 1024
checkHost: true
und weiter finden wir, dass Die base(null)
Implementierung tut nichts wirklich, aber setzen Sie die InternalFormatProvider
auf null
. Also, wenn wir halten graben wir feststellen, dass CreateFile
:
private static Stream CreateFile(string path, bool append, bool checkHost)
{
FileMode mode = append ? FileMode.Append : FileMode.Create;
return new FileStream(path, mode, FileAccess.Write, FileShare.Read, 4096, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);
}
ein FileStream
mit diesen Parameterwerten erstellt:
path: the path to the file
mode: FileMode.Append
access: FileAccess.Write
share: FileShare.Read
bufferSize: 4096
options: FileOptions.SequentialScan
msgPath: just the file name of the path provided
bFromProxy: false
useLongPath: false
checkHost: true
ein so jetzt sind wir endlich immer irgendwo, weil wir das nutzen, sind dabei zu Windows-API, und das ist, wo die Frage wirklich beginnt, weil das FileStream::ctor
eine Methode namens Init
aufruft. Es ist eine ziemlich lange Methode, aber ich bin wirklich in einer Linie interessiert:
this._handle = Win32Native.SafeCreateFile(text3,
dwDesiredAccess,
share,
secAttrs,
mode,
num,
IntPtr.Zero);
die natürlich CreateFile
nennt, wo die Parameterwerte:
text3: the full path to the file
dwDesiredAccess: 1073741824
share: 1 (FILE_SHARE_READ)
secAttrs: null
mode: 4 (OPEN_ALWAYS)
num: 134217728 | 1048576 (FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_POSIX_SEMANTICS)
so, was würde von Windows tun, wenn ich hatten zwei Threads versucht, gleichzeitig für denselben Pfad auf diesen Anruf zuzugreifen? Würde es die Datei öffnen und die Schreibvorgänge zwischenspeichern, sodass beide Benutzer in die Datei schreiben können? Oder muss ich ein Lock-Objekt und lock
um den Anruf zu AppendAllText
nutzen?
Das ist eine Idee! Mit ** einem Schreiber, der eine Warteschlange liest, ** wird das Problem drastisch vereinfacht. Ich habe mehr als ein Szenario in PROD wie dieses, aber man loggt, haben Sie ein Beispiel, das die 'BlockingCollection' zum Protokollieren praktisch verwendet? Wenn nicht, keine Sorge, ich kann es tun. –
Mach dir keine Sorgen über das Beispiel mein Freund, es ist Kuchen. Eine kurze Frage. Du hast erwähnt, dass es wahrscheinlich übertrieben war, es sei denn, es war für etwas wie Holzfällerei. Liegt das an dem Overhead des Typs selbst (d. H. In Szenarien mit niedrigeren Transaktionen würde dies Leistungsprobleme verursachen)? –
@MichaelPerrenoud - Wenn Sie es für die Protokollierung verwenden, abhängig davon, wie viel, bevorzugen Sie möglicherweise ein Protokollierungsframework wie "Log4Net", das Multithreading-Szenarien für Sie behandeln sollte http://StackOverflow.com/questions/1519211/multithread -safe-logging – keyboardP