2009-10-23 28 views
7

Trong ứng dụng của tôi, tôi có một biểu mẫu bắt đầu quá trình đồng bộ hóa và vì một số lý do tôi muốn chỉ cho phép một đồng bộ hóa chạy cùng một lúc. Vì vậy, tôi đã thêm một trường bool tĩnh vào biểu mẫu của tôi cho biết liệu đồng bộ đang được tiến hành hay chưa và thêm khóa để đặt trường này thành true nếu nó chưa được đặt sao cho luồng đầu tiên có thể bắt đầu đồng bộ hóa. sẽ cố gắng bắt đầu nó sẽ chấm dứt.Cảnh báo phân tích khóa và mã C# CA2002

Mã của tôi là một cái gì đó như thế này:

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(); 
      } 
     } 
    } 
} 

này đang làm việc tốt nhưng khi tôi chạy Mã Phân tích về dự án của tôi Tôi nhận được thông báo cảnh báo sau đây:

CA2002: Microsoft. Độ tin cậy: 'SynchronizationForm.SynchronizationForm_Shown (đối tượng, EventArgs)' khóa trên một tham chiếu của loại 'Type'. Thay thế này bằng một khóa chống lại một đối tượng có bản sắc mạnh.

Bất cứ ai có thể giải thích cho tôi điều gì sai với mã của tôi và cách tôi có thể cải thiện nó để làm cho cảnh báo biến mất. Điều đó có nghĩa là đối tượng có một bản sắc mạnh mẽ?

Trả lời

10

Điều gì là sai khi bạn đang khóa trên một cái gì đó công khai (typeof(SynchronizationForm)) mà có thể truy cập ở khắp mọi nơi từ mã của bạn và nếu một số chủ đề khác khóa trên cùng một điều này bạn sẽ có được một bế tắc. Nói chung, bạn chỉ nên khóa các đối tượng tĩnh riêng tư:

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

} 

Điều này đảm bảo rằng chỉ có SynchronizationForm có thể có khóa.

+1

Điều này đúng, nhưng việc khóa các đối tượng có "nhận dạng yếu" cũng không được khuyến khích vì các lý do khác. –

6

Từ MSDN explanation of the rule

Một đối tượng được cho là có một bản sắc yếu khi nó có thể được truy cập trực tiếp qua các biên giới miền ứng dụng. Một chuỗi cố gắng lấy khóa trên đối tượng có nhận dạng yếu có thể bị chặn bởi chuỗi thứ hai trong miền ứng dụng khác có khóa trên cùng một đối tượng.

Vì bạn không nhất thiết có thể dự đoán những gì khóa một AppDomain khác có thể mất, và vì các khóa như vậy có thể cần phải được marshalled và sau đó sẽ tốn kém, quy tắc này có ý nghĩa với tôi.

3

Vấn đề là typeof (SynchronizationForm) không phải là một đối tượng khóa riêng, có nghĩa là bất kỳ đoạn mã nào khác có thể sử dụng nó để khóa, điều này có thể dẫn đến bế tắc. Ví dụ: nếu một số mã khác đã thực hiện điều này:

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

Sau đó, bế tắc sẽ xảy ra. Thay vào đó, bạn nên delcare một đối tượng khóa riêng trong lớp SynchronizationForm và khóa trên đó thay vào đó.

2

Đối tượng của lớp có thể được sử dụng thuận tiện làm khóa loại trừ lẫn nhau cho phương pháp tĩnh của lớp.

Nguồn: http://msdn.microsoft.com/en-us/library/aa664735(VS.71).aspx

Để thêm vào câu trả lời của Doug, những gì bạn có ở đây là một cơ chế khóa mà chỉ nên được sử dụng trong phương pháp tĩnh, được sử dụng trong một phương pháp dụ.

+1

Khóa trên System.Type không còn được coi là thực hành tốt, vì những lý do được đưa ra trong MSDN bằng liên kết trong câu trả lời của Doug. Lý tưởng nhất là câu lệnh đó và ví dụ mã sẽ bị loại bỏ khỏi đặc tả ngôn ngữ C#. –

Các vấn đề liên quan