这个锁定代码有效吗?

时间:2011-02-08 17:15:39

标签: c# .net winforms multithreading locking

我有一个写入的StreamWriter。

当行数达到500时,它会关闭它并移动文件。

我已经添加了一个计时器,所以每隔5秒它关闭它并移动文件。

显然,如果计时器启动并关闭StreamWriter,然后在MyMethod中,它会尝试写入StreamWriter,它会抛出一个摇摆不定的状态。因此我添加了一些锁以尝试防止出现任何问题,因此如果计时器启动它会关闭StreamWriter,分配一个新的文件名,然后在锁定后如果MyMethod尝试写入它就全部应该没问题。

以下代码是否足以处理您认为的任何问题?

    private readonly object objLock = new object();

    private StartUpMethod()
    {
        if (tmFileWriter == null)
        {
         tmFileWriter = new Timer(5000);
         tmFileWriter.AutoReset = false;
         tmFileWriter.Elapsed += new ElapsedEventHandler(tmFileWriter_Elapsed);
        }
    }

    private void MyMethod()
    {
        lock (objLock)
        {
           if (_tempFilename == "")
           {
              _tempFilename = GenerateFileName();
             _tw = new System.IO.StreamWriter(_tempFilename);
           }
        }

         //Do some processing

         lock (objLock)
         {
            _tw.WriteLine(sql);
            _filelineCount++;
            if (_filelineCount > 500)
            {
               _tw.Close();
               System.IO.File.Move(_tempFilename, _tempFilename.Replace(".tmp", ".sql"));
               _tempFilename = "";
               _filelineCount = 0;
            }
   }

    private void tmFileWriter_Elapsed(object sender, ElapsedEventArgs e)
    {
        tmFileWriter.Stop();

        lock (objLock)
        {
            if (_tw != null)
            {
                _tw.Close();
                 System.IO.File.Move(_tempFilename, _tempFilename.Replace(".tmp", ".sql"));
                 _tempFilename = GenerateFileName();
                 _tw = new StreamWriter(_tempFilename);
             }
        }

        tmFileWriter.Start();
    }
}

4 个答案:

答案 0 :(得分:2)

这应该可以正常工作,因为它可以保护文件免受多个线程的并发访问。我唯一要改变的是将MyMethod中的两个部分组合在一起。创建文件后没有理由释放锁定,这样您就可以再次获取锁定以进行写入。所以而不是:

lock
{
  // Create file if necessary
}

lock
{
  // write to the file
}

只是做:

lock
{
  // create file if necessary
  // write to the file
}

答案 1 :(得分:1)

我看到的唯一问题是,如果计时器触发并且输入了0行,则可能会生成不必要的文件,但这可能是您想要的行为。

答案 2 :(得分:1)

我不是专家,只是一个想法。如果计时器在退出MyMethod中的第二个锁后直接激活会发生什么。

private void MyMethod() {
  lock{}
  //Do processing
  lock{}
}

它会尝试移动已移动的文件吗?

答案 3 :(得分:0)

代码看起来会起作用,但如果效率问题,我会选择使用缓冲区和使用原子交换来改变输出缓冲区的文件。

然后写入缓冲区不会涉及任何锁定,只会写入文件。