2014-05-08 31 views
1

我正在写一个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()); 
    } 

这是equivilent(我认为)

File.AppendAllText(Filepath, text.ToString()); 

很显然,在多线程环境对自己的这些言论会导致失败,以写在他们相撞时。 我已将lock放在此代码上,但这并不理想,,因为它太贵,可能会加剧此瓶颈。是否有其他方式导致一个线程文件访问阻止另一个。我被告知“阻止未锁定”,我认为lock确实阻止了,但他们必须暗示以更便宜的方式防止同时使用文件系统。

如何以较少时间花费的方式阻止执行?

+1

“因为它太昂贵,可能会加剧这一瓶颈” - 这是一种误解。锁定非常快,写入文件很慢。在大多数情况下,从多个线程写入同一个文件的速度会更慢,除非设备提供了多线程写入硬件功能(我还没有看到,但我认为它们可能存在)。 – oleksii

+3

如果该片段是瓶颈,那是因为您每次写入时都会打开和关闭文件句柄。保持文件打开并在需要时刷新写入器会快得多。 –

+0

要添加到@oleksii评论:在多数情况下,写入多个线程的相同*磁盘驱动器*的速度将会变慢。 –

回答

3

您不能让多个线程同时写入同一个文件,因此没有这样的“瓶颈”。 A 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); 
} 
+0

我相信你可以有多个线程写入同一个流(我想不出任何实际上会阻止它的东西),并且他们会写入交错(因此可能会损坏输出)。是的,您可以按照您的建议设置生产者 - 消费者,但是您发布的示例代码缺少需要的信号(日志可能不会在一个批次中添加,而只会添加一次)。因此,在这种情况下,您可能不需要'锁定',而是使用具有内置信令的'ConcurrentQueue '。 – LB2

1
+0

基于该链接的备注:_“锁定一个文件流的范围给锁定进程的线程独占访问该文件流的范围。”_我相信这将是跨进程锁定,线程在同一进程内。 – LB2

+0

是的,我错过了。这可能是对的。 – tdbeckett

+0

这是另一个使用[File.Open](http://msdn.microsoft.com/zh-cn/library/y973b725(v = vs.110).aspx)选项[FileShare.None](http: //msdn.microsoft.com/en-us/library/system.io.fileshare(v=vs.110).aspx) – tdbeckett