简体   繁体   English

在C#中调用线程并记录到文本文件的更好方法

[英]better way of invoking thread and logging to text file in C#

I have a program which write logging as Text File. 我有一个将日志记录写为文本文件的程序。

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();
            }
        }
    }
}

Then I have a function. 然后我有一个功能。

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();
}

Two of the inner functions ( BoardingPass_Print() and BaggageTag_Print() ) call the same logging function. 内部的两个函数( BoardingPass_Print()BaggageTag_Print() )调用相同的日志记录函数。

logging.log.Info(username, "Query Trace > ", sql);

Because of my invoking thread methods, I think I face the error: 由于我调用线程方法,我认为我遇到了错误:

The process cannot access the file 'C:\\Folder\\2012-01-17-Name.txt' because it is being used by another process. 该进程无法访问文件'C:\\ Folder \\ 2012-01-17-Name.txt',因为该文件正在被另一个进程使用。

Could anyone give me better solution to interact with thread and logging to text file without facing error message like this? 任何人都可以给我更好的解决方案来与线程交互并记录到文本文件,而不会遇到这样的错误消息吗?

Every suggestion will be really appreciated. 每个建议将不胜感激。

You would have to make the writing thread-safe (with lock ). 您将必须使编写线程安全(带有lock )。 Your current code also is not exception-safe. 您当前的代码也不是异常安全的。 You can solve both issues by using the right library method. 您可以使用正确的库方法来解决这两个问题。

You cannot (easily) assure safe access to a file from multiple processes, but as long as its only written by 1 instance of the application you can sync the threads. 您不能(轻松地)确保可以从多个进程安全访问文件,但是只要文件仅由应用程序的1个实例编写,就可以同步线程。

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 is a static method, it will handle the new/existing file issue and the resource management correctly. AppendAllText是静态方法,它将正确处理新文件/现有文件问题和资源管理。

您可以使用线程安全的log4net ,而不用编写自己的日志功能。

The classic version would be: 经典版本为:

  • Have a dedicated logger thread, most of the time waiting on an AutoResetEvent 拥有专用的记录器线程,大部分时间都在等待AutoResetEvent
  • Have a (threadsafe) Queue 有一个(线程安全的)队列
  • Logging is initiated by writing to that Queue and setting the AutoResetEvent 通过写入该队列并设置AutoResetEvent来启动日志记录
  • The logger thread wakes up, empties the queue into the file, then sleeps again 记录器线程唤醒,将队列清空到文件中,然后再次休眠

You can chose from a choice of predeveloped frameworks for that or roll your own in a few lines, if you want to avoid the dependency. 您可以选择为此而选择的预先开发的框架,或者如果您希望避免依赖性,则可以自己编写几行。

Like others have said use NLog, log4Net, Enterprise Library, etc. as rolling your own logging logic will not be a comprehensive as the offerings already available. 就像其他人所说的那样,请使用NLog,log4Net,企业库等,因为滚动现有的日志记录逻辑将是不全面的,因为已经提供了这些产品。

However if you want to keep things as they are... one suggestion might be to send the log information to a queue (say MSMQ) and have another separate process poll the queue and save the information to your text files. 但是,如果您希望保持原样...一个建议可能是将日志信息发送到队列(例如MSMQ),然后让另一个单独的进程轮询队列并将信息保存到文本文件中。

If you don't want to use any logging framework, you must at least use lock statement to be thread-safe. 如果您不想使用任何日志记录框架,则必须至少使用lock语句来保证线程安全。

You can also use Singleton instead of static method and keep your log file open until appliaction ends. 您也可以使用Singleton代替静态方法,并保持日志文件打开,直到应用结束。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM