TestNInja
TestNInja

Reputation: 187

How to write to a txt file when multiple processes are using it? C#

I have a logger that attempts to write log files. The issue seems to be when there are multiple processes accessing the same log file, the logger fails to write to the log file giving an error of "Another process is using the file...", causing critical information to be lost. I have tried using locks but it does not seem to work since they are separate processes ( I think that is the reason why they do not work). Is there a way to have multiple processes access the file without losing information? If not, are there any other alternatives? Thanks.

Upvotes: 8

Views: 4731

Answers (3)

LB2
LB2

Reputation: 4860

Your options in no particular order:

  1. Have different processes write to different log files. If needed, have these processes roll files at some point (like at midnight), and have another process that takes yesterday's logs and merges them together.
  2. If you own/control your logger infrastructure and must write to the same log file, the look into using named mutex. Named mutexes are system mutexes and can be shared across process boundaries. The code example at the link shows exactly how to share same mutex among processes.
    • As Florian F suggested in the comments, use log4net which can do this (in more than one way, including using named mutex). Their FAQ rightly states that there is performance issue there if you do it that way.
  3. There are ways to have shared read and shared write on the file, and then have ability to lock certain areas of the file. You could have multiple processes try and synchronize who writes into which areas of the file, lock accordingly, and so on. But this is very painful to get right and would recommend highly against it.
  4. Use syslog server.
  5. Use log4net's remote logging capabilities.

Upvotes: 7

Jorge Córdoba
Jorge Córdoba

Reputation: 52123

If you insist on reinventing the wheel and not using other options (log4net or memory mapped files) you'll need to delay writing to the file itself and just keep trying if you conflict with another thread doing the same.

Oversimplified version using a task to get a non blocking function and to show as an example (do not used as is).

public Task FlushLog(string filePath)
{
  var task = new Task(
  () => 
  while (true)
  {
     try
     {
        var file = new FileStream(filePath, FileMode.OpenOrCreate, 
                                  FileAccess.ReadWrite, FileShare.Read));
        WriteLogToFileInTheUsualWay(file);
        file.Close();
        file.Dispose();
        break;
     }
     catch (UnauthorizedAccessException exception)
     {
        // Sleep randomly and try again
        Thread.Sleep(new Random(DateTime.Now.Milliseconds).Next(1000));
     }
  }
  );
  task.Start();
  return task;
}

Upvotes: 1

Mau
Mau

Reputation: 14468

Log4Net is an option, as mentioned by Florian.

Another option is to use a separate file as a lock. If the lock file is present, other processes perform an active wait, else they create the lock file, write, then delete the lock file.

If you fail to create a lock file, it means another process got there before you and you keep waiting.

Upvotes: 3

Related Questions