代码之家  ›  专栏  ›  技术社区  ›  Len Tango Ben

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

  •  1
  • Len Tango Ben  · 技术社区  · 14 年前

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

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

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

    事先谢谢!

    顺便说一句,我也欢迎对我的代码进行任何其他改进,我觉得并不是每件事情都像它所能做到的那样高效:

    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
    
    5 回复  |  直到 13 年前
        1
  •  3
  •   Tesserex    14 年前

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

    1. 要么做一个 Init 函数,或者使用静态构造函数-在其中,启动一个新的 System.Threading.Thread 只穿过一个 while(true) 循环。
    2. 创建新的 Queue<string> 并让您的日志记录功能排队到上面。
    3. 你的 虽然(真) 循环查找队列中的项目,将其出列并记录下来。
    4. 在执行任何线程上的任何操作之前,请确保锁定队列。
        2
  •  3
  •   Andreas Niedermair    14 年前

    SRY,但您不能重新发明车轮:
    选择 log4net (或任何其他(企业)日志记录引擎)作为日志记录程序!

        3
  •  1
  •   Paul Talbot    14 年前

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

    当您启动要登录的应用程序时,请传递下面的内容,其中log file是日志文件的文件名和路径。

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

    然后您要将它放入静态日志类中。向导位是threadSafeAndEntry函数,这将确保您在正确的线程中写入代码行。

    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!");
    
        4
  •  0
  •   Daniel Brückner Pradip    14 年前

    在这种情况下,您所拥有的是一个典型的生产者-消费者场景-许多线程产生日志条目,一个线程将它们写出到一个文件中。MSDN有一个 article with sample code for this scenario .

        5
  •  0
  •   JustLoren    14 年前

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

    我会调查 BackgroundWorker 类,因为它允许您分叉可以为您进行日志记录的线程。这样你的应用程序就不会减速,任何异常都会被忽略。