Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
324 views
in Technique[技术] by (71.8m points)

c# - File sharing not working as expected

I have a file sharing issue where my process is trying to read a log file whilst it is currently still open by NLog. In diagnosing the issue, I found something surprising. The following fails:

using (var fileStream1 = new FileStream("test.file", FileMode.Append, FileAccess.Write, FileShare.Read))
using (var fileStream2 = new FileStream("test.file", FileMode.Open, FileAccess.Read, FileShare.Read))
{
}

The second FileStream constructor call fails with:

System.IO.IOException was unhandled
  Message=The process cannot access the file 'c:...est.file' because it is being used by another process.
  Source=mscorlib
  StackTrace:
       at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
       at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath)
       at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)

This is despite the fact that the first FileStream indicates its willingness to share reading. What I found even more surprising was that this works:

using (var fileStream1 = new FileStream("test.file", FileMode.Append, FileAccess.Write, FileShare.Read))
using (var fileStream2 = new FileStream("test.file", FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
}

Um, yes, requesting more access when opening the second stream actually bypasses the issue. I am completely baffled as to why that is the case, and can only assume I am misunderstanding something. I've read through the API docs but they just support my current mental model for how this should work, contrary to how it does work.

Here are some supporting quotes from the docs:

A typical use of this enumeration is to define whether two processes can simultaneously read from the same file. For example, if a file is opened and Read is specified, other users can open the file for reading but not for writing.

Here's another gem:

The following FileStream constructor opens an existing file and grants read-only access to other users (Read).

FileStream s2 = new FileStream(name, FileMode.Open, FileAccess.Read, FileShare.Read);

Can anyone shed any light on this behavior. I'm testing this on .NET 4 % Windows XP.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
 var fileStream2 = new FileStream(..., FileShare.Read)

This trips up lots of programmers. Everybody assumes that this added read sharing. It didn't, the original file access request already allowed reading and specifying it again doesn't change anything. Instead it denies write sharing. And that cannot work because somebody already got write access. And is using it, you cannot remove that right. So your request to access the file will fail.

You must include FileShare.Write.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...