質問
File.AppendAllText
複数のライターからの衝突を管理しますか?
リサーチ
MSDN のドキュメンテーションではどちらの立場も実際には示していないことに気付きました。そのため、コードを反映して、その動作を確認することにしました。以下は、から呼び出されたメソッドですFile.AppendAllText
。
private static void InternalAppendAllText(string path, string contents, Encoding encoding)
{
using (StreamWriter streamWriter = new StreamWriter(path, true, encoding))
{
streamWriter.Write(contents);
}
}
ご覧のとおり、単純にStreamWriter
. そのため、特にそれが使用するコンストラクターをもう少し深く掘り下げると、最終的にこのコンストラクターを呼び出すことがわかります。
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);
}
次の値を使用します。
path: the path to the file
append: the text to append
encoding: UTF8NoBOM
bufferSize: 1024
checkHost: true
さらに、実装は を に設定するbase(null)
だけで実際には何もしないことがわかります。したがって、掘り続けると、次のことがわかります。InternalFormatProvider
null
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);
}
次のパラメータ値で を作成しFileStream
ます。
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
Windows API を活用しようとしているので、ようやくどこかにたどり着きました。ここから、FileStream::ctor
という名前のメソッドが呼び出されるため、問題が実際に始まりますInit
。かなり長い方法ですが、私が本当に興味を持っているのは次の 1 行です。
this._handle = Win32Native.SafeCreateFile(text3,
dwDesiredAccess,
share,
secAttrs,
mode,
num,
IntPtr.Zero);
もちろんCreateFile
、これは を呼び出します。パラメーター値は次のとおりです。
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)
では、2 つのスレッドが同じパスに対して同時にその呼び出しにアクセスしようとした場合、Windows はどうするでしょうか? 両方のコンシューマがファイルに書き込めるように、ファイルを開いて書き込みをバッファリングしますか? lock
それとも、ロック オブジェクトとへの呼び出しを活用する必要がありAppendAllText
ますか?