2010-02-05 35 views
13

Tôi có nên khóa sự kiện trong trường hợp sau:Tôi có nên khóa 'sự kiện' không?

sự kiện foo;

chủ đề A: sẽ gọi foo + = handler;

chủ đề B: sẽ gọi foo - = handler;

Tôi có nên khóa foo không?

+1

Câu trả lời của Jon rất tốt, nhưng trước khi trả lời, tôi sẽ quay trở lại để hỏi tại sao bạn muốn khóa ngay từ đầu. * Bạn nghĩ mình có vấn đề gì, và tại sao bạn tin rằng khóa giải quyết nó? * Tôi có thể nghĩ về nhiều vấn đề mà bạn có thể có xung quanh các sự kiện đa luồng; bạn sẽ sử dụng các kỹ thuật khóa khác nhau tùy thuộc vào vấn đề bạn đang lo lắng. –

Trả lời

24

Khóa trên foo là một ý tưởng tồi, bởi vì giá trị sẽ thay đổi mỗi lần. Bạn nên khóa trên một biến mà không thay đổi:

private readonly object eventLock = new object(); 
private EventHandler fooHandler; 

public event EventHandler Foo 
{ 
    add 
    { 
     lock (eventLock) 
     { 
      fooHandler += value; 
     } 
    } 
    remove 
    { 
     lock (eventLock) 
     { 
      fooHandler -= value; 
     } 
    } 
} 

private void OnFoo(EventArgs e) 
{ 
    EventHandler handler; 
    lock (eventLock) 
    { 
     handler = fooHandler; 
    } 
    if (handler != null) 
    { 
     handler(this, e); 
    } 
} 

Lưu ý rằng nếu bạn sử dụng một sự kiện trường như thế nào, như thế này:

public event EventHandler Foo; 

sau đó bạn sẽ tự động nhận được một " khóa (này) "trên thêm/loại bỏ, mặc dù bạn sẽ phải tự thêm nó khi tìm nạp trình xử lý trước khi gọi nó (giả sử bạn muốn chắc chắn rằng bạn đọc giá trị được ghi gần đây nhất). Cá nhân tôi không phải là một fan hâm mộ của khóa trên "này", nhưng bạn có thể không nhớ - và nó chắc chắn làm cho mã đơn giản hơn.

+0

@Jon, tôi đang sử dụng sự kiện giống như trường, vì vậy tôi không cần phải khóa thêm/xóa, tôi có đúng không? – Benny

+0

@Jon, tôi đang gọi trình xử lý sự kiện bằng cách sử dụng sự kiện trực tiếp, như foo này(), không tìm nạp trình xử lý ra khỏi sự kiện, tôi có nên thêm khóa không? – Benny

+1

@Benny: Nếu bạn đang sử dụng sự kiện giống như trường, bạn không * có * thêm/xóa để khóa. Nếu bạn đang gọi trình xử lý sự kiện trực tiếp, bạn bảo vệ chống lại nó bằng cách nào? Lưu ý rằng bạn không thể chỉ sử dụng 'if (foo! = Null) {foo (...); } 'như' foo' có thể * trở thành * null sau khi thử nghiệm. Ngoài ra nó sẽ không đảm bảo rằng bạn sẽ nhận được giá trị mới nhất - đó là lý do tại sao tôi đã có khóa trong phương pháp 'OnFoo' của tôi. (Mô hình bộ nhớ có thể làm những điều buồn cười ...) –

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