Лучший способ вызвать поток и войти в текстовый файл в C#
У меня есть программа, которая пишет журналы в виде текстового файла.
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();
}
}
}
}
Тогда у меня есть функция.
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();
}
Две из внутренних функций (BoardingPass_Print()
а также BaggageTag_Print()
) вызвать ту же функцию регистрации.
logging.log.Info(username, "Query Trace > ", sql);
Я думаю, что из-за моих вызывающих потоковых методов я сталкиваюсь с ошибкой:
Процесс не может получить доступ к файлу "C:\Folder\2012-01-17-Name.txt", поскольку он используется другим процессом.
Может ли кто-нибудь дать мне лучшее решение для взаимодействия с потоком и входа в текстовый файл, не сталкиваясь с сообщением об ошибке, как это?
Каждое предложение будет по достоинству оценено.
5 ответов
Вы должны сделать запись потокобезопасной (с lock
). Ваш текущий код также не является безопасным для исключения. Вы можете решить обе проблемы, используя правильный метод библиотеки.
Вы не можете (легко) обеспечить безопасный доступ к файлу от нескольких процессов, но если он записан только одним экземпляром приложения, вы можете синхронизировать потоки.
private static object locker = new object();
public static void Info(string user, string info, string txt)
{
string str = Assembly.GetExecutingAssembly().GetName().CodeBase.ToString();
string str3 = ...
lock (locker)
{
File.AppendAllText(path, str3 + " " + info + " => " + txt + "\n");
}
}
AppendAllText
Это статический метод, он будет правильно обрабатывать новую / существующую проблему с файлом и управление ресурсами.
Как уже говорили другие, используйте NLog, log4Net, Enterprise Library и т. Д., Поскольку сведение собственной логики ведения журнала не будет всеобъемлющим, поскольку предложения уже доступны.
Однако, если вы хотите оставить все как есть... одним из предложений может быть отправка информации журнала в очередь (скажем, MSMQ) и другой отдельный процесс, опрашивающий очередь и сохраняющий информацию в текстовые файлы.
Вы можете использовать log4net, который является потокобезопасным, вместо того, чтобы писать свою собственную функцию журнала.
Если вы не хотите использовать какие-либо рамки ведения журнала, вы должны по крайней мере использовать lock
заявление, чтобы быть потокобезопасным.
Вы также можете использовать Singleton вместо статического метода и держать файл журнала открытым, пока не закончится приложение.
Классическая версия будет:
- Иметь выделенную цепочку логгера, большую часть времени ожидающую на AutoResetEvent
- Есть (потокобезопасная) очередь
- Ведение журнала инициируется записью в эту очередь и установкой AutoResetEvent.
- Поток логгера просыпается, очищает очередь в файл, затем снова спит
Вы можете выбрать один из заранее подготовленных фреймворков для этого или свернуть свою собственную в несколько строк, если вы хотите избежать зависимости.