I am logging to file with the following method
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();
}
}
Several different threads might write to file at the same time and in some cases they will write to the same file. To avoid problems with access denied, used by other process
I have implemented some logic as you can see.
The problem is that I am still getting access denied, used by other process
from time to time.
I have looked at the build in tracers like the TextWriterTraceListener and here I can see the following note :
If an attempt is made to write to a file that is in use or unavailable, the file name is automatically prefixed by a GUID.
So it looks like even Microsoft has problems with this? Is it a Windows problem? Is there any way to handle this becides generating a new file? Generating a new file will mess of the data flow in files a lot!
Yes. Don't write to a file from multiple threads. Create a single thread that is reponsible for file writes, and have it read what to write from a ConcurrentQueue. Any thread that needs to write should just add data to the queue.