从多个程序实例向文件写入文本

3

当我将信息写入文件并运行多个程序副本时,出现以下错误:

由于另一个进程正在使用,无法访问文件'C:\ logs \ log.txt'。

代码如下:

// create a writer and open the file
TextWriter tw2 = File.AppendText(@"C:\logs\log.txt");

// write a line of text to the file
tw2.WriteLine(Environment.NewLine);
tw2.WriteLine(DateTime.Now + " " + "IN INFOSERVCALLER");
tw2.Flush();

如何以正确的方式执行?


1
首先尝试检查文件是否正在使用,请参考此答案https://dev59.com/XnNA5IYBdhLWcg3wpvtg#937558。 - Bali C
2
@BaliC:首先检查文件是否被锁定的唯一问题是,在您检查和打开文件进行写入之间,它仍然可能被锁定。最好的方法是尝试写入文件并捕获异常(如果发生)。然后稍后再次尝试。 - Jason Down
4个回答

1

始终将此类代码封装在 using 语句中

using(TextWriter tw2 = File.AppendText(@"C:\logs\log.txt"))
{
    tw2.WriteLine(Environment.NewLine); 
    tw2.WriteLine(DateTime.Now + " " + "IN INFOSERVCALLER"); 
    //tw2.Flush();  // No need to flush because close alway flush.
}

using语句在块结束时调用tw2.Close()方法。
如果在块内部发生异常,也会执行该操作。

现在,如果应用程序的其他实例由于某种原因失败,则该文件不再被锁定。


1
这里不需要刷新缓冲区,因为隐式的关闭操作也会刷新流。 - Polyfun
“Close”和“using”都不能防止异常发生,它们只能降低异常发生的概率。仍然有可能多个程序实例同时尝试打开日志文件。必须使用适当的同步原语(如Mutex)来同步对文件的访问。 - Ňuf
@Ňuf 异常会发生,但使用块确保文件正确关闭,然后其他进程可以使用该文件而不被锁定(关于flush,您和ShellShock是正确的,复制粘贴即可 :)) - Steve
史蒂夫:问题是“如何用正确的方式做到这一点?”。当程序仍然抛出异常而不是写入文件时,我认为这不是正确的方式。即使没有“using”语句,文件也会被正确关闭,唯一的区别是'using'会立即关闭文件,而没有'using'时文件将在析构函数中稍后关闭(更晚些)。 - Ňuf

1
使用Mutex类来同步多个进程对日志文件的访问。在打开文件之前调用WaitOne,在关闭文件(Flush不足够,必须关闭文件或将其包装在using关键字中,正如其他答案所提到的)完成写入后调用ReleaseMutex。Mutex名称应以前缀“Global\”开头。

0
除了Flush之外,您还需要使用Close()来关闭文件。
此外,如果另一个程序正在同时写入该文件,则无法访问该文件(直到另一个程序调用Close()为止)。 TextWriter.Close方法

关闭writer的当前实例,并释放与writer关联的任何系统资源

在这种情况下,“系统资源”指保持锁定状态直到关闭它的文件。

0
你需要在使用文本编写器打开文件后关闭它。

所以每次操作后都要使用它。

// create a writer and open the file
TextWriter tw2 = File.AppendText(@"C:\logs\log.txt");

// write a line of text to the file
tw2.WriteLine(Environment.NewLine);
tw2.WriteLine(DateTime.Now + " " + "IN INFOSERVCALLER");
tw2.Flush();
tw2.Close(); 

然后再试着写一遍,这样就不会再出现任何问题了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接