2

My goal is to write to and read same file at same time. I cannot understand why File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read) fails because it is being used by another process. The file is created by my code and I didn't set any special attributes. Tried in both .net framework 4.8 and .net6 console apps.

        static void Main(string[] args)
        {
            const string fileName = "TestFile.txt";
            try
            {
                FileStream ws = File.Open(fileName, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read);
                Console.WriteLine("ws ok");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ws {ex.Message}");
            }

            try
            {
                FileStream rs = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
                Console.WriteLine("rs ok");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"rs {ex.Message}");
                //rs The process cannot access the file 'debugpath\TestFile.txt' because it is being used by another process.
            }
            //stream close omited
            Console.ReadKey();
        }

Have read the docs FileShare Enum but cannot find any reason. Doesn't FileShare.Read mean share the file or stream with others(threads, processes) to read?

Could anyone explain the reason, and give the correct way to read the file?

  • Hi there. Thanks for your help. Weird enough changing the FileShare-flag to FileShare.ReadWrite on the read-call fixes the issue. This is counter-intuitive to the https://docs.microsoft.com/en-us/dotnet/api/system.io.fileshare?view=net-6.0 documentation. Also, this would mean, you have to open a file you only want to read with an explicit call to File.Open which I never would do if I only plan to read (in the actual code we used Open.Read, which is setting the FileShare-Flag to read as far as I can see). Nevertheless, to give you a chance to check, I will try to make a console version. – Andreas Kreuzer Mar 21 '22 at 16:04
  • i can reproduce the issue. cannot explain either. and i made the question shorter so possibly more so users might pay attension. – Lei Yang Mar 22 '22 at 03:11
  • Hi @LeiYang thanks for that! Reads quite fine now. As stated in the comment we found a solution here. What I wonder is, why did the behavior change suddenly and why does this mean, you cannot - in such a scenario - use the methos File.OpenRead, File.ReadLines (which basically was our starting point on analysis), and so on anymore, reliably. – Andreas Kreuzer Mar 22 '22 at 06:51
  • It's one of the most misleading messages in an exception. It's *not* another process. It's your own process. You're not properly disposing `ws`. – Damien_The_Unbeliever Mar 22 '22 at 07:07
  • Thanks @Damien_The_Unbeliever. But this is not true. The sample code is written as is on purpose. The reason is that we want to write and read from the file "in parallel" to make a copy of it while it is still being written. According to Microsoft documentation, this is possible - and actually was until about a week ago. So, no in this case, the missing dispose is not the problem. Maybe the code and the text is a little bit misleading now, as it had been shortened. – Andreas Kreuzer Mar 22 '22 at 07:22
  • To emphasize it: Briefly after I put my question here, we found a solution - see my first comment: Use File.Open with FileShare.ReadWrite on the second Open operation. This solves the issue with the bad handle returned. So: Problem solved - but, does anyone know, why this behavior changed dramatically if I refer to documentation? – Andreas Kreuzer Mar 22 '22 at 07:25
  • But `FileShare.Read` is not compatible with an *existing stream* opened with `FileAccess.ReadWrite`. That's as true now as it was years ago. – Damien_The_Unbeliever Mar 22 '22 at 07:26
  • 1
    found some [useful explainations](https://stackoverflow.com/a/25098500/1518100). seems `FileShare.Read` means you want others just read the file. but `FileStream ws` is writing file, so violated. – Lei Yang Mar 22 '22 at 07:29
  • According to what we have seen in the past two years, it is and more over, refering to documentation it is still: See here: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew and https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files – Andreas Kreuzer Mar 22 '22 at 07:36
  • The only thing deficient in the documents is there emphasis on subsequent accesses, when the sharing and access modes have to be compatible with *existing* handles also. And again, no , this has not changed. Option 1) Something has suddenly changed in essentially a core I/O aspect of the windows OS and nobody has noticed or option 2) *your* code or access patterns have changed and you're now tripping over an existing bug in your code. – Damien_The_Unbeliever Mar 22 '22 at 07:40
  • Thanks @LeiYang, this link is helpful, but I still feel that the documentation is somewhat misleading. – Andreas Kreuzer Mar 22 '22 at 07:40
  • @Damien_The_Unbeliever, you are right, but what sets me up is that the original code (not the one from above, but same opening logic) has not changed in the last 6 months and was functional/working. – Andreas Kreuzer Mar 22 '22 at 07:43
  • Then likely some other change in your program has resulted in less GC pressure which means the lack of Dispose on the first stream is no longer being hidden from you by a fortuitous garbage collection. – Damien_The_Unbeliever Mar 22 '22 at 07:45
  • Just to inform you: I updated the code. I made a mistake on copying it (but it is still delivering the same result). The first handle opens the file with only FileAccess.Write. – Andreas Kreuzer Mar 22 '22 at 07:45
  • @Damien_The_Unbeliever, maybe yes. Still, what I find weird is that the documentation (see links above) for the Kernel32.dll CreateFile method states that making a first call with GENERIC_WRITE, FILE_SHARE_READ allows for a second call with GENERIC_READ, FILE_SHARE_READ which is as far as I can get from debug exactly is the case we have. – Andreas Kreuzer Mar 22 '22 at 07:49
  • 2
    If you're looking at the table [here](https://learn.microsoft.com/en-us/windows/win32/fileio/creating-and-opening-files), realise that the table is *very badly formatted*. For the line with first call `GENERIC_WRITE, FILE_SHARED_READ`, the subsequent calls that are valid are either GENERIC_READ, FILE_SHARE_WRITE or GENERIC_READ, FILE_SHARE_READ FILE_SHARE_WRITE. Notably, that final `FILE_SHARE_WRITE` belongs to the second combination, not the first. – Damien_The_Unbeliever Mar 22 '22 at 07:54
  • @Damien_The_Unbeliever.... great. Thanks for that. :( This killed my whole day yesterday. – Andreas Kreuzer Mar 22 '22 at 07:58

0 Answers0