c# - Does File.AppendAllText manage collisions (i.e. multi-user concurrency)? -
question
does file.appendalltext
manage collisions multiple writers?
research
i noticed msdn documentation doesn't provide position either way, decided i'd reflect code , see does. below called method file.appendalltext
:
private static void internalappendalltext(string path, string contents, encoding encoding) { using (streamwriter streamwriter = new streamwriter(path, true, encoding)) { streamwriter.write(contents); } }
and can see leverages streamwriter
. so, if dig little deeper that, constructor uses, find calls constructor:
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); }
with following values:
path: path file append: text append encoding: utf8nobom buffersize: 1024 checkhost: true
and further find base(null)
implementation doesn't set internalformatprovider
null
. so, if keep digging find 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); }
creates filestream
these parameter values:
path: path file mode: filemode.append access: fileaccess.write share: fileshare.read buffersize: 4096 options: fileoptions.sequentialscan msgpath: file name of path provided bfromproxy: false uselongpath: false checkhost: true
an we're getting somewhere because we're leverage windows api, , question begins because filestream::ctor
calls method named init
. it's pretty long method, i'm interested in 1 line:
this._handle = win32native.safecreatefile(text3, dwdesiredaccess, share, secattrs, mode, num, intptr.zero);
which of course calls createfile
, parameter values are:
text3: full path 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, windows if had 2 threads trying access call @ same time same path? open file , buffer writes both consumers allowed write file? or need leverage lock object , lock
around call appendalltext
?
the key method:
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); }
it's opening fileshare.read
, meaning other threads or processes can open file reading, no other process/thread can open writing.
you wouldn't want allow multiple concurrent writers. consider writing 2 large buffers. it's end being interleaved.
so, yes ... if have multiple threads might appending file, need synchronize access, lock.
another option, depending on application, have consumer thread reads text queue , appends file. way, 1 thread has access file. other threads put messages on queue writer thread services. pretty easy blockingcollection
, overkill unless you're writing file on continual basis (as in logging).
Comments
Post a Comment