I have a program which write logging as Text File.
namespace logging
{
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
public class log
{
private static string lpath;
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
public static void Info(string user, string info, string txt)
{
StreamWriter writer;
string str = Assembly.GetExecutingAssembly().GetName().CodeBase.ToString();
.....
if (!File.Exists(path))
{
writer = new StreamWriter(path, true);
writer.WriteLine(str3 + " " + info + " => " + txt);
writer.Flush();
writer.Close();
}
else
{
writer = File.AppendText(path);
writer.Write(str3 + " " + info + " => " + txt + "\n");
writer.Flush();
writer.Close();
}
}
}
}
Then I have a function.
private void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Thread thread_BP_Print = new Thread(BoardingPass_Print);
thread_BP_Print.Start();
// Simultaneously, do something on the main thread.
BaggageTag_Print();
bgw.RunWorkerAsync();
}
Two of the inner functions (BoardingPass_Print()
and BaggageTag_Print()
) call the same logging function.
logging.log.Info(username, "Query Trace > ", sql);
Because of my invoking thread methods, I think I face the error:
The process cannot access the file 'C:\Folder\2012-01-17-Name.txt' because it is being used by another process.
Could anyone give me better solution to interact with thread and logging to text file without facing error message like this?
Every suggestion will be really appreciated.
You could use log4net, which is thread safe, instead of writing your own log function.
If you don't want to use any logging framework, you must at least use
lock
statement to be thread-safe.You can also use Singleton instead of static method and keep your log file open until appliaction ends.
The classic version would be:
You can chose from a choice of predeveloped frameworks for that or roll your own in a few lines, if you want to avoid the dependency.
Like others have said use NLog, log4Net, Enterprise Library, etc. as rolling your own logging logic will not be a comprehensive as the offerings already available.
However if you want to keep things as they are... one suggestion might be to send the log information to a queue (say MSMQ) and have another separate process poll the queue and save the information to your text files.
You would have to make the writing thread-safe (with
lock
). Your current code also is not exception-safe. You can solve both issues by using the right library method.You cannot (easily) assure safe access to a file from multiple processes, but as long as its only written by 1 instance of the application you can sync the threads.
AppendAllText
is a static method, it will handle the new/existing file issue and the resource management correctly.