问题描述
我有一个多线程的 .NET Core 应用程序。应用程序的一个方面是健康检查,它解析日志文件中的错误。这是用于访问它的代码:
using StreamReader reader = new StreamReader(GetLogFile);
我注意到我偶尔会收到此错误:
2021-01-12 11:15:14.890Z ERROR APP=2227 COMP=3789 [16] 应用程序问题的健康检查检查日志在 96.2407 毫秒后引发了未处理的异常 - Logger=Microsoft.Extensions.Diagnostics.HealthChecks.DefaultHealthCheckService,Level=ERROR,ThreadId=16,Exception="System.IO.IOException: 进程无法访问文件 'c:\apps\Cb.Publisher\Logs\Cb.Publisher.log' 因为它正被另一个使用过程。
我将代码更改为:
using StreamReader reader = new StreamReader(File.OpenRead(GetLogFile));
在测试中,我没有遇到这个问题,但它发生的很少,所以我不能 100% 确定它已解决。我的更改可能会解决此问题还是有更好的方法来解决此问题?
附加信息
这是整个函数:
private int LogLine(Regex reg)
{
GetLogFile = DefaultLogFile.GetLogFileName();
using StreamReader reader = new StreamReader(File.OpenRead(GetLogFile));
string line;
int lineNo = 0;
int errorLine = 0;
while ((line = reader.ReadLine()) != null)
{
Match match = reg.Match(line);
if (match.Success)
{
errorLine = lineNumber;
}
lineNo++;
}
return errorLine;
}
如果我在 Visual Studio 中的 while
行上设置断点并运行该函数,然后尝试在记事本中编辑该文件,我将失败并显示错误 The process cannot access the file because it is being used by another process
。
经过一番调查,我想知道这条线是否真的是我的问题的原因:
var fileTarget = (FileTarget)LogManager.Configuration.FindTargetByName("file-target");
它在DefaultLogFile.GetLogFileName
:
public string GetLogFileName()
{
var fileTarget = (FileTarget)LogManager.Configuration.FindTargetByName("file-target");
var logEventInfo = new LogEventInfo();
string fileName = fileTarget.FileName.Render(logEventInfo);
if (!File.Exists(fileName))
{
throw new Exception("Log file does not exist.");
}
return fileName;
}
解决方法
您目前建议的解决方案可能就足够了,是的:
using StreamReader reader = new StreamReader(File.OpenRead(GetLogFile));
但是,正确的解决方案是检查该文件是否在您使用该文件的其他任何地方都没有被锁定。这也意味着您的日志框架(无论是 Log4Net、NLog、Serilog 等)应该正确配置为不对日志文件采取独占锁定。我相信日志框架默认情况下通常不会锁定它的读取访问权限,因此除非您自定义了配置,否则日志框架应该不成问题。