2010-08-19 34 views
23

Có thể thực thi mã sau từ nhiều luồng cùng một lúc.Thêm đại biểu vào sự kiện - an toàn luồng

this._sequencer.Completed += OnActivityFinished; 

Chủ đề có an toàn khi thêm đại biểu vào bộ xử lý sự kiện từ nhiều chuỗi không?

Chủ đề có an toàn khi xóa đại biểu đến từ trình xử lý sự kiện từ nhiều luồng không?

Cách đơn giản và bảo trì nhất để làm cho chuỗi này an toàn là gì?

Trả lời

31

Nếu bạn không xác định sự kiện riêng của bạn thêm/xóa xử lý, các biên dịch C# tạo add này handler (tái tạo bởi .NET Reflector):

public void add_MyEvent(EventHandler value) 
{ 
    EventHandler handler2; 
    EventHandler myEvent = this.MyEvent; 
    do 
    { 
     handler2 = myEvent; 
     EventHandler handler3 = (EventHandler) Delegate.Combine(handler2, value); 
     myEvent = Interlocked.CompareExchange<EventHandler>(ref this.MyEvent, handler3, handler2); 
    } 
    while (myEvent != handler2); 
} 

xóa trình xử lý trông giống nhau nhưng với Delegate.Remove thay vì Delegate.Combine.

Lưu ý việc sử dụng Interlocked.CompareExchange? Điều này ngăn điều kiện cuộc đua giữa cập nhật trường sao lưu của sự kiện và đọc từ đó. Vì vậy, nó là thread-an toàn.

+2

Một làm rõ nhỏ - đây là việc thực hiện trong .NET 4, Trước đó nó được sử dụng 'lock (this)' (cũng xem câu trả lời của desco) –

+0

@ohadsc Tôi vừa tạo một sự kiện và biên dịch với .net 2 và nó vẫn tạo ra Interlocked mã như được định nghĩa bởi timwi – Simon

+4

@Simon bạn đúng, đó là một tính năng trình biên dịch, không phải là một thời gian chạy. Tôi nên nói "đây là việc thực hiện trong trình biên dịch C# 4" –

4

Điều đó phụ thuộc vào việc triển khai sự kiện, thành thật mà nói.

Sự kiện giống trường được tạo bởi trình biên dịch C# là an toàn chỉ, nhưng nếu đó là sự kiện tùy chỉnh, ai sẽ biết? Lưu ý rằng trong ứng dụng đa luồng, bạn nên mong đợi điều kiện cuộc đua giữa thêm/xóa trình xử lý và sự kiện kích hoạt ... ví dụ: sự kiện có thể bắt đầu để kích hoạt, sau đó bạn có thể hủy đăng ký và người xử lý vẫn sẽ được gọi sau khi hủy đăng ký đó.

5

cho các sự kiện giống như trường thêm/xóa trình xử lý là an toàn chỉ. Từ thông số kỹ thuật:

Khi biên dịch sự kiện giống trường, trình biên dịch sẽ tự động tạo bộ lưu trữ để tổ chức sự kiện thêm hoặc xóa trình xử lý sự kiện vào trường đại biểu. Để an toàn thread, các thao tác bổ sung hoặc loại bỏ được thực hiện trong khi giữ khóa (§8.12) trên đối tượng chứa đối tượng sự kiện, hoặc đối tượng kiểu (§7.6.10.6) cho một sự kiện tĩnh.

Tuy nhiên nó là đúng đối với C# 3.0 và thấp hơn, trong C# 4.0 biên dịch tạo ra thực hiện lock-free sử dụng thói quen đan cài (nhưng đặc tả vẫn giữ nguyên - bug)

Trong triển khai tùy chỉnh không ai có thể nói chính xác ... ngoại trừ có lẽ tác giả của mã :)

+0

Tôi tin rằng thông số kỹ thuật đã được cập nhật, nhưng phiên bản cập nhật chưa được xuất bản. –

+0

có thể, tôi đã đề cập đến phiên bản có sẵn tại đây (xuất bản ngày \t 4/19/2010) - http://www.microsoft.com/downloads/details.aspx?FamilyID=dfbf523c-f98c-4804-afbd-459e846b268e&displaylang=vi – desco

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