.net - Is using of MemoryMappedFile instance, opened by MemoryMappedFile.OpenExisting method threadsafe? -
in wcf service need provide functionality of files downloading supporting of range
http header chunked downloading. first call getfile
method of service creates new memorymappedfile
instance file on disk. let's assume in time when mmf created first request , request still processing, second call getfile
method of service opening existing mmf , returning streamed response client. happens if mmf disposed (and source file closed on memorymappedfile disposing) thread create it? should second call read content opened viewstream or no?
i had wrote small test , seems till memorymappedfile opened openexisting
method, it's lifetime extended , source file keeps opened. true, or missed pitfall? can't find documentation such case in msdn.
update: added additional thread.sleep call after existing mmf opened before obtaining mapview of file simulate threads race
private static readonly string mapname = "foo"; private static readonly string filename = @"some big file"; static void main(string[] args) { var t1 = task.factory.startnew(openmemorymappedfile); var t2 = task.factory.startnew(readmemorymappedfile); task.waitall(t1, t2); } private static void openmemorymappedfile() { var stream = file.openread(filename); using (var mmf = memorymappedfile.createfromfile(stream, mapname, 0, memorymappedfileaccess.read, null, handleinheritability.none, false)) { console.writeline("memory mapped file created"); thread.sleep(1000); // timeout thread open existing mmf } console.writeline("memory mapped file disposed"); } private static void readmemorymappedfile() { thread.sleep(100); //wait till mmf created var buffer = new byte[1024 * 1024]; //1mb chunk long totallength = 0; using (var f = file.openread(filename)) { totallength = f.length; } using (var mmf = memorymappedfile.openexisting(mapname, memorymappedfilerights.read)) { console.writeline("existing mmf opened successfully"); thread.sleep(2000); //simulate threads race using (var viewstream = mmf.createviewstream(0, 0, memorymappedfileaccess.read)) { console.writeline("view of file mapped successfully"); file.delete(path.getfilename(filename)); using (var filestream = file.open(path.getfilename(filename), filemode.createnew, fileaccess.write)) using (var writer = new binarywriter(filestream)) { int readbytes; { readbytes = viewstream.read(buffer, 0, buffer.length); writer.write(buffer, 0, readbytes); console.write("{0:p}% of target file saved\r", filestream.length / (float)totallength); thread.sleep(10); //simulate network latency } while (readbytes > 0); console.writeline(); console.writeline("file saved successfully"); } } } }
an open view not pulled away under reading if other file handle disposed or file deleted. view stays valid until close explicitly. same goes file handles (you can delete file while handles still open , working - little known fact).
suppose closed if different file handle closed. code reading start generating access violations @ random points during execution. unsound design.
btw, threading timing-based , therefore broken. think trying create repro case can executed.
Comments
Post a Comment