我使用以下方法登录文件
public static void LogDataContractToFile(string XMLStringToLog, string filePathAndName)
{
FileInfo fileinfoMaster;
FileInfo fileinfoLog;
string fileName = string.Empty;
int tmpInt = 0;
filePathAndName = filePathAndName.ToLower();
while (true)
{
lock (LogDataContractToFileLock)
{
if (!_workingWithFiles.Contains(filePathAndName))
{
_workingWithFiles.Add(filePathAndName);
break;
}
}
Thread.Sleep(100);
}
try
{
#region Create XMLFile
if ((tmpInt = filePathAndName.LastIndexOf('.')) > 0)
fileName = filePathAndName.Remove(tmpInt, filePathAndName.Length - tmpInt);
else
fileName = filePathAndName;
fileinfoMaster = new FileInfo(fileName + ".xml");
fileinfoLog = new FileInfo(fileinfoMaster.DirectoryName + "\\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
if ((fileinfoMaster.Exists && !fileinfoLog.Exists) ||
(!fileinfoMaster.Exists && fileinfoLog.Exists))
{
fileinfoMaster.Delete();
fileinfoLog.Delete();
}
//Se så att filen är 50 MB eller mindre annars arkivera
if (fileinfoMaster.Exists && fileinfoLog.Length > 52428800)
{
tmpInt = FileWriter.FileCount(fileinfoLog.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + "*.log");
fileinfoLog.MoveTo(Path.Combine(fileinfoLog.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoLog.Name) + "_" + tmpInt.ToString() + ".log"));
CreateLogDataMasterFile(Path.Combine(fileinfoMaster.DirectoryName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + "_" + tmpInt.ToString() + ".xml"), fileinfoLog.Name);
fileinfoLog = new FileInfo(fileinfoMaster.DirectoryName + "\\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
}
if (!fileinfoMaster.Exists)
{
DirectoryInfo info = new DirectoryInfo(fileinfoMaster.DirectoryName);
if (info.Exists == false)
info.Create();
CreateLogDataMasterFile(fileinfoMaster.FullName, Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log");
}
#endregion
using (StreamWriter sw = File.AppendText(fileinfoMaster.DirectoryName + "\\" + Path.GetFileNameWithoutExtension(fileinfoMaster.Name) + ".log"))
{
sw.Write(XMLStringToLog);
sw.Flush();
}
}
finally
{
lock (LogDataContractToFileLock)
{
_workingWithFiles.Remove(filePathAndName);
}
}
}
private static void CreateLogDataMasterFile(string filepathAndName, string dataFileName)
{
XmlTextWriter xmlWriter;
using (xmlWriter = new XmlTextWriter(filepathAndName, System.Text.Encoding.UTF8))
{
xmlWriter.Formatting = Formatting.Indented;
xmlWriter.WriteStartDocument();
xmlWriter.WriteDocType("DataLog", null, null, "<!ENTITY data SYSTEM \"" + dataFileName + "\">");
xmlWriter.WriteStartElement("root");
xmlWriter.WriteRaw("&data;");
xmlWriter.WriteEndElement();
xmlWriter.Flush();
}
}
几个不同的线程可能同时写入文件,在某些情况下,它们会写入同一个文件。为了避免access denied, used by other process
出现问题,我已经实现了一些逻辑。
问题在于我仍然不时地access denied, used by other process
。
我已经看过像TextWriterTraceListener和here这样的跟踪器中的构建。我可以看到以下注释:
如果尝试写入正在使用的文件或 不可用,文件名自动以GUID为前缀。
所以看起来甚至微软都有这个问题?这是一个Windows问题吗?有没有办法处理这个因为生成一个新文件?生成一个新文件会使文件中的数据流混乱!
答案 0 :(得分:1)
是。不要从多个线程写入文件。创建一个对文件写入负责的单个线程,并让它从ConcurrentQueue读取要写入的内容。任何需要编写的线程都应该只是将数据添加到队列中。