Delphi 多个TFileStreams,TStreamWriter写入同一文件

Delphi 多个TFileStreams,TStreamWriter写入同一文件,delphi,delphi-10.3-rio,Delphi,Delphi 10.3 Rio,我开始使用TFileStream和TStreamWriter来编写简单的文本日志文件(而不是旧的Writeln(T,…))。我有多个应用程序正在写入同一个日志文件。 当然,每个应用程序都有自己的TFileStream,它们都会像这样打开文件 FFileStream:=TFileStream.Create(LogName, fmOpenReadWrite+fmShareDenyNone) FExporter:=TStreamWriter.Create(FFilestream, TEncoding.

我开始使用
TFileStream
TStreamWriter
来编写简单的文本日志文件(而不是旧的
Writeln(T,…)
)。我有多个应用程序正在写入同一个日志文件。 当然,每个应用程序都有自己的
TFileStream
,它们都会像这样打开文件

FFileStream:=TFileStream.Create(LogName, fmOpenReadWrite+fmShareDenyNone)
FExporter:=TStreamWriter.Create(FFilestream, TEncoding.UTF8);
FExporter.NewLine:=#$0A;
FExporter.AutoFlush:=TRUE;
并使用

  FExporter.BaseStream.Seek(0, soFromEnd);
  FExporter.Write('['+DateToStr(Now, FDateTimeFormat)+'] ['+TimeToStr(Now, FDateTimeFormat)+'] [#'+Lead0(GetCurrentThreadId, 5)+']: '+EntryText);
  FExporter.WriteLine;
结果有点“不令人满意”,因为线被替换,中间是空线,似乎不起作用


如何正确地执行此操作?

在多行处理中同时写入多行可能会导致意外的继续,因为并行执行

您应该确保您正在连续写入一个块,因此WriteLine应该在末尾使用换行符发送到write内部

因此,你的写作方式应该是:

  FExporter.BaseStream.Seek(0, soFromEnd);
  FExporter.Write('['+DateToStr(Now, FDateTimeFormat)+'] ['+TimeToStr(Now, FDateTimeFormat)+'] [#'+Lead0(GetCurrentThreadId, 5)+']: '+EntryText + System.slineBreak);
  //FExporter.WriteLine;
更新1: 正如Oliver发布的链接所示,如果要写入的消息大小大于OS文件扇区,有时它无法工作,而此时,其他进程也尝试写入消息。因此,在这种情况下,结果内容可能是混合的

所以,按照我的第一个目的去做,你会增加获得期望结果的概率,但在100%的情况下,这可能不是解决方案


为了100%确保使用多线程进程在单个文件中写入连续日志,您应该创建一个日志进程来接收来自其他文件的消息,并作为唯一负责在整个线程中写入同步日志的人。

在多线程进程中同时写入多行可能会导致意外的继续,因为它与执行并行

您应该确保您正在连续写入一个块,因此WriteLine应该在末尾使用换行符发送到write内部

因此,你的写作方式应该是:

  FExporter.BaseStream.Seek(0, soFromEnd);
  FExporter.Write('['+DateToStr(Now, FDateTimeFormat)+'] ['+TimeToStr(Now, FDateTimeFormat)+'] [#'+Lead0(GetCurrentThreadId, 5)+']: '+EntryText + System.slineBreak);
  //FExporter.WriteLine;
更新1: 正如Oliver发布的链接所示,如果要写入的消息大小大于OS文件扇区,有时它无法工作,而此时,其他进程也尝试写入消息。因此,在这种情况下,结果内容可能是混合的

所以,按照我的第一个目的去做,你会增加获得期望结果的概率,但在100%的情况下,这可能不是解决方案


为了100%确保使用多个进程在单个文件中写入连续日志,您应该创建一个日志进程来接收来自其他进程的消息,并作为唯一负责在整个线程中写入同步日志的人。

我可以问一下,为什么有多个应用程序使用同一个日志文件?无论如何,如果确实要这样做,您需要某种同步。您可以使用命名的互斥/信号量来同步对同一日志文件的写入,尤其是跨进程边界的写入。修改您的设计,创建一个通过IPC接收日志条目的服务,该服务会写入日志文件。请问,为什么有多个应用程序使用同一个日志文件?无论如何,如果确实要这样做,您需要某种同步。您可以使用命名的互斥/信号量来同步对同一日志文件的写入,尤其是跨进程边界的写入。修改您的设计,创建一个通过IPC接收日志条目的服务,该服务会写入日志文件,因为它无法工作。我还将自动刷新更改为false,并在写入后刷新。现在起作用:-)不,它不会起作用。@WolfgangBures:当你说它“现在起作用”时,你只试过一次吗?如果你对它进行压力测试,它是100%都有效,还是只有90%有效?50%?我(差不多两天后)还没有看到一次失败。可能只是幸运:-)它不工作,因为。我还将自动刷新更改为false,并在写入后刷新。现在起作用:-)不,它不会起作用。@WolfgangBures:当你说它“现在起作用”时,你只试过一次吗?如果你对它进行压力测试,它是100%都有效,还是只有90%有效?50%?我(差不多两天后)还没有看到一次失败。也许只是幸运:-)