лучший способ вызвать поток и войти в текстовый файл в C # - PullRequest
0 голосов
/ 17 января 2012

У меня есть программа, которая записывает логирование как текстовый файл.

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 ]

1 голос
/ 17 января 2012

Если вы не хотите использовать какую-либо инфраструктуру ведения журналов, вы должны по крайней мере использовать оператор lock для обеспечения безопасности потоков.

Вы также можете использовать Singleton вместо статическогои оставьте файл журнала открытым, пока не закончится приложение.

1 голос
/ 17 января 2012

Как и другие говорили, используйте NLog, log4Net, Enterprise Library и т. Д., Поскольку сведение собственной логики ведения журнала не будет всеобъемлющим, поскольку предложения уже доступны.

Однако, если вы хотите сохранить вещи такими, какие они есть ... одним из предложений может быть отправка информации журнала в очередь (скажем, MSMQ) и другой отдельный процесс для опроса очереди и сохранения информации в текстовых файлах.

1 голос
/ 17 января 2012

Вы можете использовать log4net , который является поточно-ориентированным, вместо написания собственной функции журнала.

1 голос
/ 17 января 2012

Классическая версия будет выглядеть следующим образом:

  • Иметь выделенный поток логгера, большую часть времени ожидающий в AutoResetEvent
  • Иметь (потокобезопасную) очередь
  • Ведение журнала инициируется записью в эту очередь и установкой AutoResetEvent
  • Поток регистратора просыпается, очищает очередь в файл, а затем снова спит

Вы можете выбрать один из следующих вариантов:Если вы хотите избежать зависимости, то заранее подготовленные фреймворки для этого или сворачивать свои собственные в несколько строк.

1 голос
/ 17 января 2012

Вы должны сделать запись безопасной для потока (с 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 - это статический метод, он будет правильно обрабатывать новую / существующую проблему с файлом и управлять ресурсами.

...