【问题标题】:C# lock and code analysis warning CA2002C#锁和代码分析警告CA2002
【发布时间】:2009-10-23 13:49:49
【问题描述】:

在我的应用程序中,我有一个启动同步过程的表单,出于多种原因,我希望一次只运行一个同步。因此,我在表单中添加了一个静态 bool 字段,指示同步是否正在进行中,并添加了一个锁以将此字段设置为 true(如果尚未设置),以便第一个线程可以开始同步,但是当它运行所有其他线程时将尝试启动它会终止。

我的代码是这样的:

internal partial class SynchronizationForm : Form
{
    private static volatile bool workInProgress;

    private void SynchronizationForm_Shown(object sender, EventArgs e)
    {
        lock (typeof(SynchronizationForm))
        {
            if (!workInProgress)
            {
                workInProgress = true;
            }
            else
            {
                this.Close();
            }
        }
    }
}

这运行良好,但是当我对我的项目运行代码分析时,我收到以下警告消息:

CA2002 : Microsoft.Reliability : 'SynchronizationForm.SynchronizationForm_Shown(object, EventArgs)' 锁定类型为 'Type' 的引用。将其替换为针对具有强标识的对象的锁。

谁能向我解释我的代码有什么问题以及如何改进它以使警告消失。对象具有强标识是什么意思?

【问题讨论】:

    标签: c# locking code-analysis


    【解决方案1】:

    问题是你锁定了一些公共的东西 (typeof(SynchronizationForm)),它可以从你的代码中随处访问,如果其他线程锁定在同一东西上,你就会陷入死锁。一般来说,最好只锁定私有静态对象:

    private static object _syncRoot = new object();
    ...
    lock (_syncRoot) 
    {
    
    }
    

    这可以保证只有SynchronizationForm 可以拥有锁。

    【讨论】:

    • 这是对的,但出于其他原因也不建议锁定具有“弱身份”的对象。
    【解决方案2】:

    来自MSDN explanation of the rule

    当一个对象可以跨应用程序域边界直接访问时,它被称为具有弱标识。尝试获取具有弱标识的对象上的锁的线程可能会被另一个应用程序域中的另一个线程阻止,该线程在同一对象上具有锁。

    由于您不一定能预测另一个 AppDomain 可能会使用什么锁,并且由于此类锁可能需要编组并且成本很高,因此这条规则对我来说很有意义。

    【讨论】:

      【解决方案3】:

      问题是 typeof(SynchronizationForm) 不是私有锁对象,这意味着任何其他代码都可以使用它来锁定,这可能会导致死锁。例如,如果其他一些代码这样做:

      var form = new SynchronizationForm();
      lock(typeof(SynchronizationForm))
      {
          form.SomeMethodThatCausesSynchronizationForm_ShownToBeCalled();
      }
      

      然后就会发生死锁。相反,您应该在 SynchronizationForm 类中删除一个私有锁定对象并锁定它。

      【讨论】:

        【解决方案4】:

        类的System.Type对象可以方便地用作类的静态方法的互斥锁。

        来源:http://msdn.microsoft.com/en-us/library/aa664735(VS.71).aspx

        补充道格的答案,你这里有一个锁定机制,它应该只在静态方法中使用,在实例方法中使用。

        【讨论】:

        • 锁定 System.Type 不再被认为是好的做法,原因是 MSDN 中 Doug 的答案中的链接给出的原因。理想情况下,该语句和代码示例将从 C# 语言规范中删除。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-09
        相关资源
        最近更新 更多