最佳实践 - 锁定文件和线程之间的共享

时间:2012-06-29 13:05:55

标签: c# .net winforms locking filestream

背景:我有几个不同的线程,每个线程都需要写入日志文件(.txt)。我需要一种在线程之间共享此文件的方法,但我不知道如何去做这个,我已经读过可能使用某种队列,并轮询此队列将消息推送到文本文件等。或者我是否需要锁定文件并将消息放入队列中以便在完成一个前面后写入?

目前我写的是这样的;

  fileToWrite = new System.IO.StreamWriter(DeviceManager.logPath + correctDateTimeFormat);

但是我收到了错误消息;

 The process cannot access the file 'filename' because it is being used by another process.

我只能假设多个线程正在尝试同时访问它。

有人能指出我应该采用什么方法来正确指导我吗?

2 个答案:

答案 0 :(得分:2)

这是您面临的两个不同问题。

  1. 在文件关闭之前再次打开文件 - 这可以通过打开适当的共享标志来完成
  2. 同步对它的访问。可以通过使用一些互斥锁一次只允许1个线程访问该文件来完成此操作。这很重要,因为否则,您可能会有线程同时写入文件,这可能会导致问题,例如在self之间传递消息。
  3. 这个带有FileSharing参数的FileStream constructor可以帮助您在关闭文件之前从少数线程中打开文件。

    但是,根据您的需要,如果您将访问文件(例如,日志文件)集中在一个地方(创建一个类,其中有一个实例可以控制对此特定文件的访问),那就更好了。确保它会通过锁定一些私有互斥锁来同步来自不同线程的访问,因此您不会同时从几个线程写入文件。

    非常简单的例子,需要建立:

    class Logger : IDisposable
    {
        private FileStream file; //Only this instance have a right to own it
        private StreamWriter writer;
        private object mutex; //Mutex for synchronizing
    
        public Logger(string logPath)
        {
            file = new FileStream(logPath);
            writer = new StreamWriter(file);
            mutex = new object();
        }
    
        // Log is thread safe, it can be called from many threads
        public void Log(string message)
        {
            lock (mutex)
            {
                 writer.WriteLine(message);
            }
        }
    
        public void Dispose()
        {
              writer.Dispose(); //Will close underlying stream
        }
    }
    

    再一次,这很简单,只是为了展示我们在这里想要达到的基本规则。

    你在这里没有其他选择:

    1. 使用现成的日志库(Log4Net或NLog(我个人更喜欢))
    2. 日志可以向队列添加消息,你可以有另一个线程,内部记录器从这个队列读取消息并写入它们,这样,Logger的调用者就不必等待日志消息来完成记录

答案 1 :(得分:1)

请看这篇文章,了解如何在wpf中使用log4net http://codetechnics.blogspot.com/2010/09/how-to-configure-initialize-and-using.html 如果您收到错误 找不到类型或命名空间名称'log4net'(您是否缺少using指令或程序集引用?)

因为 log4net 显然需要访问客户端配置文件中未包含的 system.web.dll 强>

打开项目的属性页面,将 目标框架 设置为 .Net Framework 4 并保存更改。