简体   繁体   English

如何在多个进程使用时写入txt文件? C#

[英]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. 谢谢。

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). 正如Florian F在评论中建议的那样,使用log4net可以做到这一点(不止一种方式,包括使用命名的互斥锁)。 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. 使用syslog服务器。
  5. Use log4net's remote logging capabilities. 使用log4net的远程日志记录功能。

Log4Net is an option, as mentioned by Florian. 正如Florian所提到的,Log4Net是一个选项。

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. 如果您未能创建锁定文件,则意味着在您继续等待之前,另一个进程已到达此处。

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. 如果您坚持重新发明轮子而不使用其他选项(log4net或内存映射文件),则需要延迟写入文件本身,如果与另一个执行相同操作的线程发生冲突,请继续尝试。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM