【发布时间】:2020-08-28 06:28:29
【问题描述】:
我创建了一个简单的 Logger 类,它使用 StreamWriter 将文本附加到日志文件。主程序是一个任务调度器,它异步执行任务,并在执行成功与否时写入日志文件。 该程序从数据库中读取并将任务添加到列表中,并且 ExecuteAll() 方法异步执行该列表中的每个任务。如果读取\写入数据库或任务执行中的任何步骤出错 - 我使用 Logger.Error()。
当我运行程序时一切正常,但是当我将 Thread.Sleep(5000) 添加到每个任务以模拟连接到 API 时,我得到一个 IOExecption:
System.IO.IOException: The process cannot access the file 'Log.txt' because it is being used by another process.
记录器类:
public class Logger
{
const string filePath = @"Log.txt";
private static readonly object writerLock = new object();
public static string Info(string log)
{
string logMessage = DateTime.Now.ToString(dateTimeFormat) + " | INFO | " + log;
lock (writerLock)
{
using (StreamWriter logToFile = File.AppendText(filePath))
{
logToFile.WriteLine(logMessage);
Console.WriteLine(logMessage);
}
}
return logMessage;
}
public static string Error(string log)
{
string logMessage = DateTime.Now.ToString(dateTimeFormat) + " | ERROR | " + log;
lock (writerLock)
{
using (StreamWriter logToFile = File.AppendText(filePath))
{
logToFile.WriteLine(logMessage);
Console.WriteLine(logMessage);
}
}
return logMessage;
}
}
异步方法:
public void ExecuteJob(Job job)
{
try
{
Thread.Sleep(5000);
job.Execute(); // Executes: Log.Info("Job Executed.");
}
catch(Exception ex)
{
Logger.Error($"Couldn't Execute Job #{job.jobId}: " + ex);
}
finally
{
DbManager.UpdateJobInTable(job.jobId);
jobs.Remove(job);
}
}
//Execute all jobs
public async void ExecuteAll()
{
if (!jobs.Any())
return;
List<Task> tasks = new List<Task>();
foreach (Job job in jobs.ToArray())
{
tasks.Add(
Task.Run(() =>
{
ExecuteJob(job);
})
);
}
await Task.WhenAll(tasks);
}
当一个线程已经在使用它时,为什么锁不阻止线程进入 StreamWriter?为什么当我在没有 Thread.Sleep(5000) 的情况下运行程序时它似乎工作正常?
希望有人可以提供帮助。提前致谢。
【问题讨论】:
-
你说错误是“多进程”?
-
@RonD 是否有其他代码(Logger 除外)可以将数据读/写到
Log.txt?当错误发生时,您是否能够确保程序的其他实例没有运行? -
@RodD,无法重现此问题。此代码应该可以工作,请确保您的应用程序只有一个实例正在运行,并且该文件不会被任何其他应用程序或您应用程序中的任何其他代码访问。
-
为什么要重新发明轮子?使用现有的ReadWriterLock 支持多线程写入。我也确信多线程日志库也存在。
-
这段代码没有任何问题(好吧,除了不必要地发明了一个日志系统);锁定是正确的。我的第一个猜测是您的代码正在运行防病毒程序;他们中的一些人喜欢检查刚刚编写的文件。
标签: c# multithreading locking task streamwriter