【问题标题】:Is this locking code efficient?这个锁定代码有效吗?
【发布时间】:2011-02-08 17:15:39
【问题描述】:

我有一个被写入的 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();
    }
}

【问题讨论】:

  • 异常、错误、黑洞:-)
  • @Jon:但为什么“摇摆不定”?这是某种伦敦押韵俚语吗?
  • 是的,我想说的更多英语俚语
  • @siride:根据dictionary.reference.com/browse/wobbly3。俚语 throw a wobbly 突然变得非常激动或生气。 也许我很奇怪,但我马上就理解了“throw a wobbly”。

标签: c# .net winforms multithreading locking


【解决方案1】:

这应该很好用,因为它可以保护文件免受多个线程的并发访问。我唯一要改变的是将MyMethod 中的两个部分结合起来。创建文件后没有理由释放锁,只是为了您可以再次获得锁以便写入。所以而不是:

lock
{
  // Create file if necessary
}

lock
{
  // write to the file
}

只要做:

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

【讨论】:

  • 我在两个锁定区域之间有一些代码,我为这个问题删除了这些代码,但感谢您的回答。
  • @Jon: 中间的代码是使用_tw 还是_tempFilename?如果没有,Jim 的建议会好很多。
【解决方案2】:

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

【讨论】:

  • 谢谢,如果我没有在计时器启动时重置行数并且当它向新创建的文件写入新行时它已经为 500,那么该文件将只有 1 行在里面
【解决方案3】:

如果计时器在退出 MyMethod 中的第二个锁后立即触发会发生什么。

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

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

【讨论】:

    【解决方案4】:

    代码看起来可以工作,但如果效率是一个问题,我会选择使用缓冲区并使用原子交换来更改将缓冲区输出到哪个文件。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 2022-06-12
      相关资源
      最近更新 更多