1

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

这有可能以某种方式实现吗?最好的方法是什么?

它有点简短的描述,但我希望这个想法很清楚。如果没有,请告诉我。

提前致谢!

顺便说一句,我也欢迎对我的代码进行任何其他改进,但我感觉并非一切都尽可能高效:

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
4

5 回答 5

3

对不起,但您可能不会重新发明轮子:
选择log4net(或任何其他(企业)日志记录引擎)作为您的记录器!

于 2010-06-02T12:57:28.743 回答
3

如果您将此作为练习(仅使用现成的记录器不是一种选择),您可以尝试生产者/消费者系统。

  1. 为您的记录器创建一个Init函数,或者使用静态构造函数 - 在其中启动一个 new System.Threading.Thread,它只是通过一个while(true)循环运行。
  2. 创建一个新的Queue<string>并将您的日志记录功能排入队列。
  3. 您的while(true)循环在队列中查找项目,将它们出列并记录它们。
  4. 确保在对任一线程执行任何操作之前锁定队列。
于 2010-06-02T13:02:12.513 回答
1

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

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

Log.OnNewLogEntry += Log.WriteToFile (LogFile, Program.AppName);

然后你想把它放在你的静态 Logging 类中。向导位是 ThreadSafeAddEntry 函数,这将确保您在正确的线程中编写代码行。

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!");
于 2010-06-02T13:10:52.940 回答
0

在这种情况下,您所拥有的是典型的生产者消费者场景 - 许多线程产生日志条目,一个线程将它们写入文件。MSDN 有一篇文章,其中包含此方案的示例代码

于 2010-06-02T13:00:26.213 回答
0

对于初学者,您的日志记录机制通常应该避免抛出异常。日志机制经常是错误被写入的地方,所以当它们也开始出错时事情会变得很糟糕。

我会研究BackgroundWorker类,因为它允许您分叉可以为您进行日志记录的线程。这样您的应用程序就不会变慢,并且引发的任何异常都会被忽略。

于 2010-06-02T13:02:10.533 回答