2011-08-11 30 views
7

Tôi có EventHandler sau:Invoke của một EventHandler

private EventHandler<MyEventArgs> _myEventHandler; 
public event EventHandler<MyEventArgs> MyEvent 
{ 
    add { _myEventHandler += value; } 
    remove { _myEventHandler -= value; } 
} 

ai đó có thể giải thích sự khác biệt giữa các đoạn sau đây?
Snippet EventHandler (A):

//Snippet A: 
if (_myEventHandler != null) 
{ 
    _myEventHandler(new MyEventArgs()); 
} 

Snippet BeginInvoke (B):

//Snippet B: 
if (_myEventHandler != null) 
{ 
    _myEventHandler.BeginInvoke(new MyEventArgs(), ar => 
    { 
    var del = (EventHandler<MyEventArgs>)ar.AsyncState; 
    del.EndInvoke(ar); 
    }, _myEventHandler); 
} 

Để làm rõ: sự khác biệt giữa cách gọi một EventHandler "chỉ vì nó là" và sử dụng BeginInvoke là gì?

Trả lời

12

Cách tiếp cận BeginInvoke không đồng bộ, có nghĩa là phương pháp này được đưa ra trên một chuỗi khác. Điều này có thể nguy hiểm nếu mọi người không mong đợi nó, và rất hiếm khi xảy ra sự kiện - nhưng nó có thể hữu ích.

Ngoài ra, lưu ý rằng nói đúng bạn nên ảnh chụp giá trị xử lý sự kiện - đây là đặc biệt đúng if (qua Begin*), bạn đang đối phó với chủ đề.

var tmp = _myEventHandler; 
if(tmp != null) { 
    tmp(sender, args); 
} 

Ngoài ra - lưu ý rằng đăng ký sự kiện của bạn chính nó là không an toàn chủ đề; một lần nữa, chỉ có vấn đề này nếu bạn đang đối phó với multi-threading, nhưng inbuilt lĩnh vực như sự kiện thread-safe:

public event EventHandler<MyEventArgs> MyEvent; // <===== done; nothing more 

Những vấn đề tránh ở đây là:

  • với ảnh chụp , chúng tôi tránh nguy cơ hủy đăng ký cuối cùng giữa việc kiểm tra không thực hiện và lời gọi (điều đó có nghĩa là họ có thể nhận được sự kiện mà họ không mong đợi, nhưng điều đó có nghĩa là chúng tôi không giết chủ đề nâng cao)
  • bằng thay đổi sự kiện giống như trường, chúng tôi tránh nguy cơ mất đăng ký/hủy đăng ký khi hai luồng đang làm điều này cùng một lúc
+1

Nó không nhất thiết phải được gọi trên một chủ đề khác là nó? Gọi một đại biểu không đồng bộ vẫn được thực hiện trên cùng một luồng nhưng trả về thời điểm nó chặn AFAIK. –

+1

@Jeff no; gọi một đại biểu không đồng bộ có nghĩa là nó xảy ra trên một chuỗi công nhân. Làm thế nào khác nó sẽ chạy không đồng bộ? Lưu ý rằng điều này là khác nhau một cách tinh tế với Control.BeginInvoke mà * có thể * tiếp tục trên cùng một chuỗi nếu bạn đã ở trên giao diện người dùng –

+0

Nếu đại biểu được gọi đang thực hiện điều khiển IO (tức là khối) được trả về trang cuộc gọi. Khi hoàn thành, chuỗi ban đầu bị gián đoạn để hoàn thành phần còn lại của phương thức. Khi tôi hiểu nó, không có chủ đề mới được tạo ra, đó là tất cả các ngắt từ đó. –

5

BeginInvoke() gọi immediatelly trả về kiểm soát để các thread kêu gọi và chạy một đại biểu trong một thread riêng biệt từ ThreadPool, vì vậy đây sẽ là một số loại thực không đồng bộ.

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