C# 这个锁定代码有效吗?

C# 这个锁定代码有效吗?,c#,.net,winforms,multithreading,locking,C#,.net,Winforms,Multithreading,Locking,我有一个StreamWriter,可以写信给他 当行数达到500时,它将关闭行数并移动文件 我还添加了一个计时器,因此每隔5秒它就会关闭它并移动文件 显然,如果计时器启动并关闭StreamWriter,然后在MyMethod中尝试写入StreamWriter,它将抛出抖动。因此,我添加了一些锁,以尝试防止任何问题,因此如果计时器启动,它将关闭StreamWriter,分配一个新文件名,然后在锁定之后,如果MyMethod尝试写入,则一切都应该正常 您认为下面的代码是否足以处理任何问题 p

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

这应该可以很好地工作,因为它可以防止文件被多个线程并发访问。我唯一要更改的是将
MyMethod
中的两个部分合并在一起。没有理由在创建文件后释放锁,只是为了再次获得锁以便写入。因此,不是:

lock
{
  // Create file if necessary
}

lock
{
  // write to the file
}
只要做:

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

这应该可以很好地工作,因为它可以防止文件被多个线程并发访问。我唯一要更改的是将
MyMethod
中的两个部分合并在一起。没有理由在创建文件后释放锁,只是为了再次获得锁以便写入。因此,不是:

lock
{
  // Create file if necessary
}

lock
{
  // write to the file
}
只要做:

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

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

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

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


那么写入缓冲区就不会涉及任何锁,只有写入文件才会有锁。

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


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

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

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

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

如果计时器在退出MyMethod中的第二个锁后直接启动,会发生什么

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

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

例外,错误,黑洞:-)@Jon:但为什么会“摇摆”?那是伦敦腔的押韵俚语吗?是的,我更喜欢英语俚语say@siride:根据:3。俚语摇摇晃晃突然变得非常激动或生气。也许我很奇怪,但我马上就明白了“抛出抖动”。例外、错误、黑洞:-)@Jon:但为什么是“抖动”?那是伦敦腔的押韵俚语吗?是的,我更喜欢英语俚语say@siride:根据:3。俚语摇摇晃晃突然变得非常激动或生气。也许我很奇怪,但我马上就明白了“抛出抖动”。我在两个锁定区域之间有一些代码,我为这个问题删除了它们,但谢谢你的回答。@Jon:中间的代码是使用
\u tw
还是
\u tempFilename
?如果没有,吉姆的建议就更好了。我在两个锁区之间有一些代码,我为这个问题删除了它们,但谢谢你的回答。@Jon:中间的代码是使用
\u tw
还是
\u tempFilename
?如果没有,Jim的建议会更好。谢谢,很好的发现,如果我在计时器启动时没有重置行数,并且当它向新创建的文件写入新行时,行数已经为500,那么该文件中只有一行,很好的发现,如果我在计时器启动时没有重置行数,并且当它向新创建的文件写入新行时,行数已经为500,那么该文件中只有一行