简体   繁体   English

在文件系统级别同步写入文件

[英]Synchronize writing to a file at file-system level

I have a text file and multiple threads/processes will write to it (it's a log file).我有一个文本文件,多个线程/进程将写入它(它是一个日志文件)。

The file gets corrupted sometimes because of concurrent writings.该文件有时会因为并发写入而损坏。

I want to use a file writing mode from all of threads which is sequential at file-system level itself.我想从所有线程中使用文件写入模式,该模式在文件系统级别本身是顺序的。

I know it's possible to use locks (mutex for multiple processes) and synchronize writing to this file but I prefer to open the file in the correct mode and leave the task to System.IO .我知道可以使用锁(多个进程的互斥锁)并同步写入该文件,但我更喜欢以正确的模式打开文件并将任务留给System.IO

Is it possible ?可能吗 ? what's the best practice for this scenario ?这种情况的最佳做法是什么?

Your best bet is just to use locks/mutexex.你最好的选择就是使用锁/互斥锁。 It's a simple approach, it works and you can easily understand it and reason about it.这是一种简单的方法,它有效,您可以轻松理解它并对其进行推理。

When it comes to synchronization it often pays to start with the simplest solution that could work and only try to refine if you hit problems.在同步方面,通常从可行的最简单解决方案开始,并且只有在遇到问题时才尝试改进。

To my knowledge, Windows doesn't have what you're looking for.据我所知,Windows 没有您想要的。 There is no file handle object that does automatic synchronization by blocking all other users while one is writing to the file.没有文件句柄对象通过在写入文件时阻止所有其他用户来自动同步。

If your logging involves the three steps, open file, write, close file, then you can have your threads try to open the file in exclusive mode ( FileShare.None ), catch the exception if unable to open, and then try again until success.如果您的日志记录涉及打开文件、写入、关闭文件三个步骤,那么您可以让您的线程尝试以独占模式( FileShare.None )打开文件,如果无法打开则捕获异常,然后重试直到成功. I've found that tedious at best.我发现这充其量是乏味的。

In my programs that log from multiple threads, I created a TextWriter descendant that is essentially a queue.在从多个线程记录的程序中,我创建了一个本质上是一个队列的TextWriter后代。 Threads call the Write or WriteLine methods on that object, which formats the output and places it into a queue (using a BlockingCollection ).线程调用该对象上的WriteWriteLine方法,这些方法格式化输出并将其放入队列中(使用BlockingCollection )。 A separate logging thread services that queue--pulling things from it and writing them to the log file.一个单独的日志线程服务于队列——从中拉出东西并将它们写入日志文件。 This has a few benefits:这有几个好处:

  • Threads don't have to wait on each other in order to log线程不必为了记录而相互等待
  • Only one thread is writing to the file只有一个线程正在写入文件
  • It's trivial to rotate logs (ie start a new log file every hour, etc.)轮换日志很简单(即每小时启动一个新的日志文件等)
  • There's zero chance of an error because I forgot to do the locking on some thread出错的可能性为零,因为我忘记在某个线程上进行锁定

Doing this across processes would be a lot more difficult.跨流程执行此操作会困难得多。 I've never even considered trying to share a log file across processes.我什至从未考虑过尝试跨进程共享日志文件。 Were I to need that, I would create a separate application (a logging service).如果我需要它,我会创建一个单独的应用程序(一个日志服务)。 That application would do the actual writes, with the other applications passing the strings to be written.该应用程序将执行实际的写入操作,而其他应用程序则传递要写入的字符串。 Again, that ensures that I can't screw things up, and my code remains simple (ie no explicit locking code in the clients).同样,这确保了我不会搞砸,并且我的代码保持简单(即客户端中没有明确的锁定代码)。

您也许可以使用File.Open()并将FileShare值设置为None ,并让每个线程在无法访问文件时等待。

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

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