我正在使用foreach和任务从网上下载图像,并在本地保存它们。 执行此操作后,我写入日志,说下载文件名等。问题是我预见到两个任务可能会同时尝试写入日志导致错误。 我希望能够锁定日志,如果任何其他任务正在写入它但我不确定如何? 到目前为止,我有:
int filesDownloaded = 0;
foreach (var fileName in ListOfFileNames)
{
Task.Factory.StartNew(() =>
{
//Download File
}
lock (thislock)
{
Log.WriteLine(string.Format("Downloaded File: {0}", f.FullName), Log.Status.Success);
}
filesDownloaded++;
}
我是否需要锁定filesDownloaded
变量,或者这是一个简单的++操作无关紧要?
修改
静态日志类:
public enum Status
{
Info,
Error,
Success
}
private static string Directory { get; set; }
public static void CheckandCreateLogDirectory(string directoryPath)
{
if (!System.IO.Directory.Exists(directoryPath))
{
System.IO.Directory.CreateDirectory(directoryPath);
}
Directory = directoryPath;
}
public static void WriteLine(string writeLine, Status status)
{
if (Directory == null)
{
CheckandCreateLogDirectory(".\\Log\\");
}
using (System.IO.StreamWriter objWriter = new System.IO.StreamWriter(Directory + "Log" + DateTime.Now.ToString("ddMMyyyy") + ".log", true))
{
objWriter.WriteLine(string.Format("[{0}] {1}\t{2}", DateTime.Now, status.ToString(), writeLine));
}
}
答案 0 :(得分:1)
查看代码时会想到两件事:
1)将您的锁定移动到WriteLine()方法 - 每次要记录某些内容时都不必重复代码
private static object _lockMe = new object();
public static void WriteLine(string writeLine, Status status)
{
lock(_lockMe)
{
if (Directory == null)
{
CheckandCreateLogDirectory(".\\Log\\");
}
using (System.IO.StreamWriter objWriter = new System.IO.StreamWriter(Directory + "Log" + DateTime.Now.ToString("ddMMyyyy") + ".log", true))
{
objWriter.WriteLine(string.Format("[{0}] {1}\t{2}", DateTime.Now, status.ToString(), writeLine));
}
}
}
2)您正在工作线程中下载文件,但是在您将工作人员排队后更新日志 - 这将在文件下载之前完成。因此,我将记录INTO移动到工作线程,如下所示:
int filesDownloaded = 0;
foreach (var fileName in ListOfFileNames)
{
Task.Factory.StartNew((path) =>
{
DownloadMyFile(path);
Log.WriteLine(string.Format("Downloaded File: {0}",path), Log.Status.Success);
lock (thislock)
{
filesDownloaded++;
}
}, fileName);
}
答案 1 :(得分:0)
我是否需要锁定filesDownloaded变量,或者这很简单 ++操作没关系吗?
是的,但最好还是使用System.Threading.Interlocked.Increment
。这必须在您的任务范围内或通过延续完成,否则您将遇到计时问题。 (下载次数与目标中预期的文件不匹配)
不要"锁定"围绕您的日志记录代码(客户端)。保护对记录器(Log类)中文件的访问。在这里,我建议使用System.Threading.Mutex
以防多个进程尝试写入单个文件(就好像您运行了多个应用程序实例一样)。