2009-05-03 6 views
17

Bạn đề xuất cách nào tốt nhất để tránh đăng ký sự kiện trùng lặp? nếu dòng mã này thực thi ở hai nơi, sự kiện sẽ chạy hai lần. Tôi đang cố gắng tránh các sự kiện của bên thứ ba đăng ký hai lần.Tránh đăng ký sự kiện trùng lặp trong C#

theOBject.TheEvent += RunMyCode; 

Trong setter đại biểu của tôi, tôi có hiệu quả có thể chạy này ...

theOBject.TheEvent -= RunMyCode; 
theOBject.TheEvent += RunMyCode; 

nhưng là cách tốt nhất?

Trả lời

19

Tôi nghĩ, cách hiệu quả nhất, là làm cho sự kiện của bạn một tài sản và thêm ổ khóa đồng thời với nó như trong này Example:

private EventHandler _theEvent; 
private object _eventLock = new object(); 
public event EventHandler TheEvent 
{ 
    add 
    { 
     lock (_eventLock) 
     { 
      _theEvent -= value; 
      _theEvent += value; 
     } 
    } 
    remove 
    { 
     lock (_eventLock) 
     { 
      _theEvent -= value; 
     } 
    } 
} 
+2

Dave Morton đã thay đổi miền của mình. URL mới là: http://codinglight.blogspot.com/2009/02/preventing-duplicate-subscriptions-to.html –

+0

FYI, nếu bạn nhận được 503 tại liên kết, chỉ cần làm mới trang. Nó dường như tải sau một vài lần thử cho tôi. – Dan

1

Nếu bạn sở hữu nguồn cho lớp củaObject, khi đó bạn có quyền truy cập vào Danh sách yêu cầu của TheEvent. Bạn có thể triển khai trình bổ sung thêm của riêng bạn cho sự kiện và kiểm tra trước khi thêm.

Tuy nhiên, tôi nghĩ rằng cách tiếp cận của bạn cũng tốt.

2

là mã đa của bạn luồng? Khóa đồng thời là cần thiết chỉ khi đa luồng của nó. Nếu không phải là một chi phí của nó.

Do đó cách tiếp cận hủy đăng ký và đăng ký của bạn là chính xác.

Cảm ơn

0

Tôi sử dụng cách tiếp cận của bạn ngoại trừ một chi tiết. Tôi nghĩ rằng, các sự kiện đó sẽ được đăng ký khi bạn tạo phiên bản mới của người đăng ký hoặc theObject, điều này làm cho mã thẳng hơn. Vì vậy, tất cả những gì bạn cần chỉ là cẩn thận xem sau khi xử lý đúng đối tượng (vứt bỏ patten là giải pháp tiện lợi cho việc này).

Bạn đã đề cập rằng bạn sử dụng sự kiện của bên thứ ba, điều đó có nghĩa là bạn không thể cung cấp sự hiện thực của riêng bạn cho các phương pháp thêm/xóa, như bạn đã được thông báo. Nhưng trong các lớp học của riêng bạn với các sự kiện của riêng bạn, bạn nên xác định thực hiện của riêng bạn của các phương pháp thêm/xóa cho sự kiện để giải quyết vấn đề của bạn.

4

Tôi đã thực hiện việc này trước khi .... giả định có thể chấp nhận rằng người đăng ký cuối cùng là những gì được gọi.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyObject my = new MyObject(); 
      my.Changed += new EventHandler(my_Changed); 
      my.Changed += new EventHandler(my_Changed1); 

      my.Update(); 
      Console.ReadLine(); 
     } 

     static void my_Changed(object sender, EventArgs e) 
     { 
      Console.WriteLine("Hello"); 
     } 
     static void my_Changed1(object sender, EventArgs e) 
     { 
      Console.WriteLine("Hello1"); 
     } 
    } 
    public class MyObject 
    { 
     public MyObject() 
     { 
     } 
     private EventHandler ChangedEventHandler; 
     public event EventHandler Changed 
     { 
      add 
      { 
       ChangedEventHandler = value; 
      } 
      remove 
      { 
       ChangedEventHandler -= value; 
      } 
     } 
     public void Update() 
     { 
      OnChanged(); 
     } 

     private void OnChanged() 
     { 
      if (ChangedEventHandler != null) 
      { 
       ChangedEventHandler(this, null); 
      } 
     } 
    } 
} 
+4

tốt đẹp, cho những người đọc tốc độ có thể đã bỏ lỡ nó, đây là dòng quan trọng. ChangedEventHandler = value; thay vì + =. Tốt cho chỉ sử dụng một lần - có thể hoạt động đối với tôi trong một số trường hợp - cảm ơn bạn! – ScottCate