2009-10-23 47 views
7

在我的應用程序中,我有一個表單啓動同步過程,並且出於許多原因,我希望一次只允許一次同步運行。所以我在表單中添加了一個靜態bool字段,指示同步是否正在進行,並添加了一個鎖,將該字段設置爲true,如果它尚未設置,以便第一個線程可以開始同步,但是當它運行每個其他線程將嘗試啓動它將終止。C#鎖定和代碼分析警告CA2002

我的代碼是這樣的:

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:微軟。可靠性:'SynchronizationForm.SynchronizationForm_Shown(object,EventArgs)'鎖定類型'Type'的引用。將其替換爲具有強身份的對象的鎖。

任何人都可以向我解釋我的代碼有什麼問題,我該如何改進它以使警告消失。這個對象具有強烈的身份是什麼意思?

回答

10

什麼是錯誤的是,你正在鎖定一些公開的東西(typeof(SynchronizationForm)),它可以從你的代碼中隨處訪問,並且如果某個其他線程鎖定了同一個東西,你會遇到死鎖。一般而言,只鎖定私有靜態對象是個好主意:

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

} 

這樣可以保證你,這是唯一的SynchronizationForm可能擁有的鎖。

+1

這是事實,但鎖定具有「弱身份」的對象也不適用於其他原因。 – 2009-10-23 13:56:49

6

MSDN explanation of the rule

的對象被說成具有一個弱的身份時,它可以跨應用程序域邊界直接訪問。試圖獲得對具有弱身份的對象的鎖的線程可以被鎖定在同一對象上的不同應用程序域中的第二線程阻塞。

由於您不一定能夠預測另一個AppDomain可能需要鎖定哪些鎖,並且由於此類鎖可能需要編組並且會很昂貴,所以這條規則對我來說很有意義。

3

問題是typeof(SynchronizationForm)不是私有鎖對象,這意味着任何其他代碼片段都可能使用它來鎖定,這可能導致死鎖。例如,如果其他代碼是這樣做的:

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

然後會發生死鎖。相反,你應該修改SynchronizationForm類中的私有鎖對象並鎖定它。

2

System.TypeSystem.Type對象可以方便地用作類的靜態方法的互斥鎖。

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

要添加到道格的答案,你在這裏的是一個鎖定機制,應僅在靜態方法中使用,在一個實例方法被使用。

+1

因爲在MSDN中由Doug的答案中的鏈接給出的理由,鎖定System.Type不再被認爲是好的做法。理想情況下,該語句和代碼示例將從C#語言規範中刪除。 – 2012-05-15 08:08:35

相關問題