C# 静态记录器在单独的线程中?

C# 静态记录器在单独的线程中?,c#,logging,synchronization,logfiles,C#,Logging,Synchronization,Logfiles,我制作了一个日志记录器,它记录一个字符串,一个静态类和一个静态类 因此,我可以从我的整个项目中调用它,而无需创建实例。 很好,但是我想让它在一个单独的线程中运行,因为访问文件需要时间 这有可能吗?最好的方法是什么 这是一个简短的描述,但我希望这个想法是明确的。如果没有,请告诉我 提前谢谢 顺便说一句,我的代码上的任何其他改进都是受欢迎的,我觉得并不是每件事都像它可能的那样高效: internal static class MainLogger { internal sta

我制作了一个日志记录器,它记录一个字符串,一个静态类和一个静态类 因此,我可以从我的整个项目中调用它,而无需创建实例。 很好,但是我想让它在一个单独的线程中运行,因为访问文件需要时间

这有可能吗?最好的方法是什么

这是一个简短的描述,但我希望这个想法是明确的。如果没有,请告诉我

提前谢谢

顺便说一句,我的代码上的任何其他改进都是受欢迎的,我觉得并不是每件事都像它可能的那样高效:

internal static class MainLogger
    {
        internal static void LogStringToFile(string logText)
        {
            DateTime timestamp = DateTime.Now;
            string str = timestamp.ToString("dd-MM-yy  HH:mm:ss ", CultureInfo.InvariantCulture) + "\t" + logText + "\n";
            const string filename = Constants.LOG_FILENAME;
            FileInfo fileInfo = new FileInfo(filename);
            if (fileInfo.Exists)
            {
                if (fileInfo.Length > Constants.LOG_FILESIZE)
                {
                    File.Create(filename).Dispose();
                }
            }
            else
            {
                File.Create(filename).Dispose();
            }
            int i = 0;
            while(true)
            {
                try
                {
                    using (StreamWriter writer = File.AppendText(filename))
                    {
                        writer.WriteLine(str);
                    }
                    break;
                }
                catch (IOException)
                {
                    Thread.Sleep(10);
                    i++;
                    if (i >= 8)
                    {
                        throw new IOException("Log file \"" + Constants.LOG_FILENAME + "\" not accessible after 5 tries");
                    }
                }
            }
        }
    }
enter code here

sry,但您不能重新发明车轮:
选择或任何其他企业日志引擎作为记录器

sry,但您不能重新发明轮子:
选择或任何其他企业日志引擎作为记录器

在本例中,您遇到的是一个典型的生产者-消费者场景—许多线程生成日志条目,而一个线程将它们写到一个文件中。MSDN有一个.

本例中的情况是一个典型的生产者-消费者场景-许多线程生成日志条目,一个线程将它们写入一个文件。MSDN有一个。

对于初学者,您的日志机制通常应该避免引发异常。通常,日志机制是错误写入的地方,因此当它们也开始出错时,情况就变得糟糕了


我将研究这个类,因为它允许您分叉可以为您做日志记录的线程。这样你的应用程序就不会慢下来,任何引发的异常都会被忽略。

首先,你的日志机制通常应该避免引发异常。通常,日志机制是错误写入的地方,因此当它们也开始出错时,情况就变得糟糕了


我将研究这个类,因为它允许您分叉可以为您做日志记录的线程。这样你的应用程序就不会慢下来,任何引发的异常都会被忽略。

如果你只是在练习中使用现成的记录器,你就不能尝试生产者/消费者系统

为记录器创建一个Init函数,或者使用静态构造函数——在它内部,启动一个新的System.Threading.Thread,它只运行一个whiletrue循环。 创建一个新队列,并将您的日志记录函数放入队列中。 whiletrue循环查找队列中的项目,将其出列并记录它们。 在任何线程上对队列执行任何操作之前,请确保锁定队列。
如果您只是在练习中使用现成的记录器,那么您可以尝试使用生产者/消费者系统

为记录器创建一个Init函数,或者使用静态构造函数——在它内部,启动一个新的System.Threading.Thread,它只运行一个whiletrue循环。 创建一个新队列,并将您的日志记录函数放入队列中。 whiletrue循环查找队列中的项目,将其出列并记录它们。 在任何线程上对队列执行任何操作之前,请确保锁定队列。
好的,简单地说,您需要创建一个线程安全的静态类。下面是一些代码片段,一个从任何线程调用的委托,它指向正确的线程,然后该线程调用WriteToFile函数

启动要登录的应用程序时,请将以下内容传递给它,其中LogFile是日志文件的文件名和路径

Log.OnNewLogEntry += Log.WriteToFile (LogFile, Program.AppName);
然后你想把它放在你的静态日志类中。向导位是ThreadSafeAdEntry函数,这将确保您处于正确的线程中,可以将代码行写入

public delegate void AddEntryDelegate(string entry, bool error);

public static Form mainwin;

public static event AddEntryDelegate OnNewLogEntry;

public static void AddEntry(string entry) {
  ThreadSafeAddEntry( entry, false );
}

private static void ThreadSafeAddEntry (string entry, bool error)
    {
    try
        {
        if (mainwin != null && mainwin.InvokeRequired)  // we are in a different thread to the main window
            mainwin.Invoke (new AddEntryDelegate (ThreadSafeAddEntry), new object [] { entry, error });  // call self from main thread
        else
            OnNewLogEntry (entry, error);
        }
    catch { }
    }

public static AddEntryDelegate WriteToFile(string filename, string appName) {
    //Do your WriteToFile work here
    }
}
最后写一行

Log.AddEntry ("Hello World!");

好的,简单地说,您需要创建一个线程安全的静态类。下面是一些代码片段,一个从任何线程调用的委托,它指向正确的线程,然后该线程调用WriteToFile函数

启动要登录的应用程序时,请将以下内容传递给它,其中LogFile是日志文件的文件名和路径

Log.OnNewLogEntry += Log.WriteToFile (LogFile, Program.AppName);
然后你想把它放在你的静态日志类中。向导位是ThreadSafeAdEntry函数,这将确保您处于正确的线程中,可以将代码行写入

public delegate void AddEntryDelegate(string entry, bool error);

public static Form mainwin;

public static event AddEntryDelegate OnNewLogEntry;

public static void AddEntry(string entry) {
  ThreadSafeAddEntry( entry, false );
}

private static void ThreadSafeAddEntry (string entry, bool error)
    {
    try
        {
        if (mainwin != null && mainwin.InvokeRequired)  // we are in a different thread to the main window
            mainwin.Invoke (new AddEntryDelegate (ThreadSafeAddEntry), new object [] { entry, error });  // call self from main thread
        else
            OnNewLogEntry (entry, error);
        }
    catch { }
    }

public static AddEntryDelegate WriteToFile(string filename, string appName) {
    //Do your WriteToFile work here
    }
}
最后写一行

Log.AddEntry ("Hello World!");

我完全同意不要从头开始写一个新的记录器。但我不确定log4net或类似的东西是否支持在一个单独的线程上运行I/O操作,是否使用异步I/O或其他什么。因此,在现有记录器上堆叠一点代码来实现这一点可能是有效的。。。我们在各种多线程场景中使用log4net,而且它很有效!谢谢,显然我不是唯一一个在这方面挣扎的人。然而,我想完全自己做一些东西,我喜欢重新发明轮子+1建议使用预卷库-2没有理由,OP想了解如何做到这一点,我绝对同意不要从头开始编写新的记录器。但我不确定是log4net还是什么
类似的支持在单独的线程上运行I/O操作,如果它们使用异步I/O或其他什么。因此,在现有记录器上堆叠一点代码来实现这一点可能是有效的。。。我们在各种多线程场景中使用log4net,而且它很有效!谢谢,显然我不是唯一一个在这方面挣扎的人。然而,我想完全自己做一些东西,我喜欢重新发明轮子+1建议使用预卷库-2没有理由,OP想了解如何做,Thnanks,这应该很容易。我已经为它编写了类似的代码来与COMport通信,它甚至没有占用我1%的CPU btwThnanks,这应该很容易。我已经为它编写了类似的代码来与COMport进行通信,它甚至没有占用我1%的CPU btwThanks,我将与TesserexThanks的解决方案一起使用类似的东西,我将与Tesserex的解决方案一起使用类似的东西