File sharing not working as expected

Deadly 提交于 2019-12-03 05:31:54
 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.

What actually happens, is that the fileStream2 can not change the subsequent access to a file which already is open for writing (or appending) by fileStream1.

fileStream2 will successfully open the file leaving a FileShare.Read as "legacy" for subsequent access only if there are no processes which already have Write file access to it. Even more, in our example we are talking about the same process. It wouldn't make too much sense to modify a file stream's properties from another file stream, wouldn't it?

Maybe the following comparison explains it even better:

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

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

In my opinion, the description phrase for FileShare.Read:

Allows subsequent opening of the file for reading.

should be read as

The subsequent access to the file is restricted only for reading, including the access of already existing locks.

[Update]

I haven't parsed through the code, but it seems that these two links could shed some light over the internal functioning of the constructor:

The internal FileStream ctor

The internal FileStream Init method

I think I've found the answer in the documentation for CreateFile.

In the discussion of the dwShareMode parameter, it says:

FILE_SHARE_READ 0x00000001 Enables subsequent open operations on a file or device to request read access. Otherwise, other processes cannot open the file or device if they request read access. If this flag is not specified, but the file or device has been opened for read access, the function fails.

FILE_SHARE_WRITE 0x00000002 Enables subsequent open operations on a file or device to request write access. Otherwise, other processes cannot open the file or device if they request write access. If this flag is not specified, but the file or device has been opened for write access or has a file mapping with write access, the function fails.

That fundamentally changes my understanding of how file sharing works.

Fourth parameter you pass

share
A constant that determines how the file will be shared by processes.

determines in what mode others can open the file. So obviously - when you're trying to open the file with fileshare mode "read" and already have the same file open in Write mode - operation fails.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!