C# 在文件系统级别同步对文件的写入

C# 在文件系统级别同步对文件的写入,c#,concurrency,filesystems,writing,C#,Concurrency,Filesystems,Writing,我有一个文本文件,多个线程/进程将写入它(它是一个日志文件) 文件有时会由于并发写入而损坏 我想从所有线程使用一种文件写入模式,这种模式在文件系统级别上是连续的 我知道可以使用锁(多进程互斥)并同步写入此文件,但我更喜欢以正确的模式打开文件,并将任务留给System.IO 可能吗?此场景的最佳实践是什么?您可以使用设置为None的值,如果无法访问文件,则让每个线程等待。您最好的选择就是使用锁/互斥锁。这是一个简单的方法,它是有效的,你可以很容易地理解它和理由 说到同步,从最简单的可行解决方案开始

我有一个文本文件,多个线程/进程将写入它(它是一个日志文件)

文件有时会由于并发写入而损坏

我想从所有线程使用一种文件写入模式,这种模式在文件系统级别上是连续的

我知道可以使用锁(多进程互斥)并同步写入此文件,但我更喜欢以正确的模式打开文件,并将任务留给
System.IO


可能吗?此场景的最佳实践是什么?

您可以使用设置为
None
的值,如果无法访问文件,则让每个线程等待。

您最好的选择就是使用锁/互斥锁。这是一个简单的方法,它是有效的,你可以很容易地理解它和理由


说到同步,从最简单的可行解决方案开始,并且只有在遇到问题时才尝试改进,这通常是值得的。

据我所知,Windows没有您想要的。没有一个文件句柄对象通过在用户写入文件时阻止所有其他用户来执行自动同步

如果日志记录涉及打开文件、写入文件和关闭文件这三个步骤,则可以让线程尝试以独占模式(
FileShare.None
)打开文件,如果无法打开,则捕获异常,然后重试,直到成功。我觉得这充其量也很乏味

在从多个线程登录的程序中,我创建了一个本质上是队列的
TextWriter
子代。线程调用该对象上的
Write
WriteLine
方法,格式化输出并将其放入队列(使用
BlockingCollection
)。一个单独的日志线程服务队列——从中提取内容并将其写入日志文件。这有几个好处:

  • 线程不必互相等待以进行日志记录
  • 只有一个线程正在写入文件
  • 轮换日志很简单(即每小时启动一个新的日志文件等)
  • 因为我忘了在某个线程上执行锁定,所以发生错误的可能性为零

跨流程执行此操作要困难得多。我甚至从未考虑过尝试跨进程共享日志文件。如果需要,我将创建一个单独的应用程序(日志服务)。该应用程序将执行实际写入操作,其他应用程序将传递要写入的字符串。同样,这确保了我不会把事情搞砸,我的代码保持简单(即客户端中没有显式锁定代码)。

我认为这会导致访问异常,除非有阻塞调用或等待句柄。这确实会导致异常。@Xaqron目前无法测试它,如果您尝试在同一台机器上运行所有进程,或者您正在访问网络共享上的文件,请告诉我该怎么办?我不认为(但我不是100%肯定)有办法在“等待直到可以锁定”类型的共享模式下打开文件。我认为做你想做的事情的唯一方法就是使用互斥。当然,如果您要在网络共享上打开一个文件,这也不是解决方案,那么您可能需要设置一个服务器来进行日志调用。@Lasse:同一台计算机(windows)上的所有线程/进程实际上我对写操作没有足够的控制权。我使用
Debug.Write
然后
Flush
,但内容似乎并没有完全在
Flush
之后写入磁盘。但是我可以选择打开/共享模式和.NET writer对象(现在我使用
TextWriter
)@Xaqron。我认为您可以很容易地切换到打开、刷新和关闭文件的文件写入机制。但是,性能是否足够取决于您希望记录的速率,以及您希望多准确地表示来自不同进程的交错。如果我无法在文件系统级别解决此问题,然后使用
IPC
对于
多进程
场景是必要的,这对于简单的记录器来说不是一个好方法(我不认为著名的记录器是这样做的)。我同意这不太理想,但在文件系统级别上似乎没有任何自动同步。我可能错了,但仔细阅读相关文档并没有发现任何东西。如果你遇到什么,请告诉我们。还有,你在说什么“著名的伐木工人”?