C# 写入文件系统。如何有效锁定

C# 写入文件系统。如何有效锁定,c#,multithreading,filesystems,locking,C#,Multithreading,Filesystems,Locking,我正在将Stringbuilder写入文件 using (FileStream file = new FileStream(Filepath, FileMode.Append, FileAccess.Write, FileShare.Read)) using (StreamWriter writer = new StreamWriter(file, Encoding.Unicode)) { writer.Write(text.ToString()); }

我正在将
Stringbuilder
写入文件

   using (FileStream file = new FileStream(Filepath, FileMode.Append, FileAccess.Write, FileShare.Read))
   using (StreamWriter writer = new StreamWriter(file, Encoding.Unicode))
   {
        writer.Write(text.ToString());
   }
这是相当的(我认为)

显然,在多线程环境中,这些语句本身会在冲突时导致写入失败。
我在这段代码上加了一个
,但这并不理想,因为它太贵,可能会加剧这个瓶颈。是否有其他方法导致一个线程的文件访问阻止另一个线程的文件访问。有人告诉我“阻止而不是锁定”,我以为
lock
确实阻止了,但他们肯定暗示了一种更便宜的方法来防止同时使用文件系统


如何以时间开销较小的方式阻止执行?

不能让多个线程同时写入同一个文件,因此,不存在这样的“瓶颈”。一个
对于这个场景来说非常有意义。如果您担心这会很昂贵,只需将写操作添加到队列中,并让单个线程管理将它们写入文件

伪码

public static readonly Object logsLock = new Object();

// any thread
lock(logsLock) 
{
    logs.Add(stringBuilderText);
}

// dedicated thread to writing
lock(logsLock)
{
    // ideally, this should be a "get in, get out" situation, 
    // where you only need to make a copy of the logs, then exit the lock, 
    // then write them, then lock the logsLock again, and remove only the logs 
    // you successfully wrote to to file, then exit the lock again.
    logs.ForEach(writeLogToFile);
}

您不能让多个线程同时写入同一个文件,因此,不存在这样的“瓶颈”。一个
对于这个场景来说非常有意义。如果您担心这会很昂贵,只需将写操作添加到队列中,并让单个线程管理将它们写入文件

伪码

public static readonly Object logsLock = new Object();

// any thread
lock(logsLock) 
{
    logs.Add(stringBuilderText);
}

// dedicated thread to writing
lock(logsLock)
{
    // ideally, this should be a "get in, get out" situation, 
    // where you only need to make a copy of the logs, then exit the lock, 
    // then write them, then lock the logsLock again, and remove only the logs 
    // you successfully wrote to to file, then exit the lock again.
    logs.ForEach(writeLogToFile);
}

可以使用lock方法锁定流


您可以使用锁定方法锁定流



“因为它太贵,可能会加剧这一瓶颈”——这是一种误解。锁的速度非常快,写入文件的速度很慢。在大多数情况下,从多个线程写入同一文件的速度会更慢,除非设备提供多线程写入硬件功能(我没有看到任何,但我认为它们可能存在)。如果该片段是一个瓶颈,那是因为每次写入时都要打开和关闭文件句柄。保持文件打开并在需要时刷新写入程序会快得多。添加到@oleksii注释:在大多数情况下,从多个线程写入同一磁盘驱动器的速度会慢得多。我认为更大的惩罚是不断地打开和关闭流(它们是您拥有代码的方式,每个线程都会这样做),而不是锁定。在您的上下文中锁定似乎并不坏,但我会创建一次流,并在线程之间共享,然后锁定它,以提高效率—保持文件打开的好处。我突然想到要使用后台进程,但我认为这样做太过分了。我会保持现状,如果这是一个瓶颈,重新评估这个决定。“因为它太贵了,可能会加剧这个瓶颈”——这是一个误解。锁的速度非常快,写入文件的速度很慢。在大多数情况下,从多个线程写入同一文件的速度会更慢,除非设备提供多线程写入硬件功能(我没有看到任何,但我认为它们可能存在)。如果该片段是一个瓶颈,那是因为每次写入时都要打开和关闭文件句柄。保持文件打开并在需要时刷新写入程序会快得多。添加到@oleksii注释:在大多数情况下,从多个线程写入同一磁盘驱动器的速度会慢得多。我认为更大的惩罚是不断地打开和关闭流(它们是您拥有代码的方式,每个线程都会这样做),而不是锁定。在您的上下文中锁定似乎并不坏,但我会创建一次流,并在线程之间共享,然后锁定它,以提高效率—保持文件打开的好处。我突然想到要使用后台进程,但我认为这样做太过分了。我将保持原样,如果这是一个瓶颈,请重新评估该决定。根据该链接的评论:“锁定文件流的某个范围会使锁定进程的线程独占访问该文件流的某个范围。”我相信这将用于跨进程锁定,在同一进程内不交叉线程。这里是另一个选项,用于选项谢谢。但是,我不确定Fileshare。None是一个有效的选项,因为我非常确定如果另一个线程命中该文件,它不会被阻止,它会被阻止。可能会,但根据另一篇帖子,对该文件的请求将被排队。基于该链接的评论:“锁定文件流的某个范围会使锁定进程的线程独占访问该文件流的某个范围。”我相信这将用于跨进程锁定,而不是同一进程内的跨线程锁定。下面是该选项的另一个用法,谢谢。但是,我不确定Fileshare。None是一个有效的选项,因为我非常确定如果另一个线程命中该文件,它不会被阻止,它会被阻止。可能会,但根据另一篇帖子,对该文件的请求将被排队。我相信您可以让多个线程写入同一个流(我想不出任何实际可以阻止它的事情),并且它们会交错写入(因此可能会破坏输出)。是的,您可以按照建议设置producer-consumer,但是您发布的示例代码缺少所需的信号(日志可能不是在一个批次中添加的,而且只添加一次)。因此,在这种情况下,您可能不需要
lock
,而是使用带有内置信号的
ConcurrentQueue
。我相信您可以让多个线程写入同一个流(我想不出任何实际阻止它的方法),它们将以交错方式写入(因此可能会破坏输出)。是的,您可以按照建议设置producer-consumer,但是您发布的示例代码缺少所需的信号(日志可能不是在一个批次中添加的,而且只添加一次)。因此,在这种情况下,您可能不需要
锁定
,而是使用具有内置信令的
ConcurrentQueue