1

I have a network consisting of multiple computers, for simplicity take two, Computer_A and Computer_B. On one of those, Computer_A, lies a text file with settings. One process on Computer_B should write some lines to that text file. Another process on Computer_A should monitor the file for changes, and when such a change occurs, read in the lines. Here is important that the process on Computer_A can be sure that the file has be written completely and it doesn't read half-written lines.

What I have is:

-> For Computer_B, which does the writing:

using (FileStream fileStream = new FileStream(@"file_on_computer_A", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read))
    {
      using (StreamWriter WriteToFile = new System.IO.StreamWriter(fileStream))
      { 
         WriteToFile.WriteLine("setting one");
         WriteToFile.WriteLine("setting two");
         //...
      }
    }

-> Computer_A, uses FileSystemWatcher to monitor changes to the file

        FSW = new FileSystemWatcher();
        FSW.Path = @"local_directory_path";
        FSW.Filter = "PLSanDM.txt";
        FSW.Changed += new FileSystemEventHandler(PLSanDM);
        FSW.EnableRaisingEvents = true;

and as for the reading itself when the Event FSW.Changed fires:

 void PLSanDM(object sender, FileSystemEventArgs e)
    {
            using (FileStream fs = new FileStream(@"path_to_file", FileMode.Open, FileAccess.Read))
            {
                using (ReadFromFile = new System.IO.StreamReader(fs))
                {
                    List<string> linesInFile = new List<string>();
                    string line;
                    while ((line = ReadFromFile.ReadLine()) != null)
                    {
                        linesInFile.Add(line);
                    }
                    foreach (string s in linesInFile)
                    {
                      //do sth
                    }
                }
           }
    }

This however leads to a Exception stating that the file is currently used by another process and it cannot be opened.

What am I doing wrong that leads to the exception and what is a correct solution? What do I have to change to make sure Computer_A can only read the file after Computer_B has finished writing it and not during the writing?

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
AlexGuevara
  • 932
  • 11
  • 28
  • @DarinDimitrov why did the [duplicate about shared locks](http://stackoverflow.com/questions/1409492/read-from-a-growing-file-in-c) not answer this question? – CodeCaster Jan 05 '16 at 16:43
  • 1
    Because the *duplicate question* is about single process synchronization which can be trivially solved with a `lock` keyword. This question is about inter-process synchronization and even more: inter-process synchronization across the network which is a far more different (and difficult) problem. There's a great difference between multi-thread, multi-process and multi-machines synchronization. – Darin Dimitrov Jan 05 '16 at 16:44
  • @Darin my bad, seems like I used the wrong duplicate. Anyway there's plenty of questions about this, and the relevant terms are in the one I linked to (shared readwrite lock). Anyway, OP, please share your research. – CodeCaster Jan 05 '16 at 16:52
  • @CodeCaster What exactly shall I share? There are indeed lots of questions on this topic on StackOverflow, and I read most of them. Shall I post the links? Most of them deal with synchronization between threads, which is easy to solve (by using a Boolean as lock for example, as DarinDimitrov mentioned). Multi-process can mostly be solved by using the `EventWaitHandle` like [here](http://stackoverflow.com/questions/18690537/multi-processes-readwrite-one-file). Events fired on one machine are not received (automatically) by other machines -> multi-machine problem (my case as far as i can tell). – AlexGuevara Jan 05 '16 at 17:01
  • Well, the question I linked to tasks about the FileShare enum, which can be used to let multiple processes access the same file at the same time. Will that suffice? See for example http://stackoverflow.com/questions/9759697/reading-a-file-used-by-another-process and other Q&As found through "c# read file in use write by other process". The question _I_ would like to ask myself first is _" Do I want to rely on the filesystem and SMB for this?"_, but that may not be open for discussion in your case. – CodeCaster Jan 05 '16 at 17:07
  • I already use the FileShare enum (see code above), possibly wrong? I do not think that the linked question solves mine. – AlexGuevara Jan 05 '16 at 17:11

1 Answers1

1

Here's a file-lock project on GitHub which could be used to synchronize the access to a shared resource - a file in your case. So when a process on Computer_B needs to write to the file it will try to acquire a lock, write to the file and release the lock. At the same time, a process on Computer_A will be notified by the FileSystemWatcher that the file is currently being written to and attempt to acquire a lock. If this fails it can retry until it succeeds or times out. When it succeed to acquire the lock it can safely read the contents of the file.

This technique has the advantage to not depend on some OS specific features like Mutexes or named event handles.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928