2009-02-10 27 views
15

Theo sau từ câu hỏi BeginInvoke()/EndInvoke() của tôi, có sự khác biệt lớn về hiệu suất/bất kỳ thứ gì khác giữa Đại biểu. BeginInvoke() và sử dụng QueueUserWorkItem() để gọi một delegate không đồng bộ?Sự khác nhau giữa QueueUserWorkItem() và BeginInvoke(), để thực hiện một hoạt động không đồng bộ không có kiểu trả về là cần thiết

+0

Bạn cũng có thể muốn xem: http://marcgravell.blogspot.com/2009/02/async-without-pain.html –

Trả lời

17

http://blogs.msdn.com/cbrumme/archive/2003/07/14/51495.aspx

nói:

"Một thực tế đáng ngạc nhiên là điều này là cũng tại sao Delegate.BeginInvoke/ EndInvoke đang quá chậm so với kỹ thuật tương đương như ThreadPool.QueueUserWorkItem (hoặc UnsafeQueueUserWorkItem nếu bạn hiểu ý nghĩa bảo mật và muốn thực sự hiệu quả) .Mã số cho BeginInv oke/EndInvoke nhanh chóng biến thành mã thông báo thông báo chung của lộ trình từ xa chung . "

+0

Hmmm, cảm ơn, đó là cả hai thú vị và rất đáng sợ. Tôi nghĩ rằng tôi sẽ quay trở lại bất kỳ BeginInvoke()/EndInvoke() mã mà không yêu cầu giá trị trả lại! – endian

21

Điều quan trọng tôi có thể nghĩ đến với QueueUserWorkItem là bạn phải sử dụng các loại WaitCallback đại biểu, trong đó trông phức tạp nếu bạn đã có một trường hợp SomeRandomDelegate và một số args. Tin tốt là bạn có thể sửa lỗi này với một kết thúc:

ThreadPool.QueueUserWorkItem(
    delegate { someDelegate(arg1, arg2); } 
); 

mô hình này cũng đảm bảo bạn sẽ có được gõ mạnh thích hợp tại thời gian biên dịch (không giống như đi qua một arg object nhà nước để QueueUserWorkItem và đúc nó trong phương pháp mục tiêu). Mô hình này cũng có thể được sử dụng khi gọi phương pháp trực tiếp:

ThreadPool.QueueUserWorkItem(
    delegate { SomeMethod(arg1, arg2); } 
); 

Rõ ràng, không có EndInvoke tương đương, bạn cũng không thể có được một giá trị trả lại ra trừ khi bạn gọi một phương thức/nâng cao một sự kiện/etc ở cuối của phương pháp của bạn ... trên một lưu ý liên quan, bạn cần phải cẩn thận với exception handling.

+3

Gặp phải tình huống chính xác này là lần đầu tiên tôi tự nghĩ, "Wow, tôi yêu đóng cửa. " –

+0

Wow, đây là một mẹo cực kỳ. Nó cảm thấy như một ngữ nghĩa boxing/unboxing, và tôi tưởng tượng không tốn kém hơn, trong một kế hoạch rộng lớn của sự vật. –

+0

Rất tiếc, về mặt kỹ thuật, nó phải là "đại biểu (đối tượng o)" hoặc tương tự để mã biên dịch, tôi tin rằng, vì QueueUserWorkItem mong đợi chữ ký ủy nhiệm khớp với WaitCallback, tức là một chữ bao gồm một tham số duy nhất của đối tượng kiểu. –

-1

Không nên có bất kỳ sự khác biệt lớn nào, tôi cũng nghĩ rằng BeginInvoke/EndInvoke được tạo cho một đại biểu sử dụng nhóm luồng để thực thi.

-1

Không được có bất kỳ sự khác biệt về hiệu suất nào, vì cả Delegate.BeginInvoke và ThreadPool.QueueUserWorkItem sẽ thực thi trên một chuỗi chủ đề chuỗi.

Sự khác biệt lớn nhất là nếu bạn gọi BeginInvoke, bạn bắt buộc phải gọi EndInvoke tại một số điểm. Ngược lại, ThreadPool.QueueUserWorkItem là "lửa và quên". Điều đó có lợi ích và hạn chế. Lợi ích là bạn có thể quên nó. Hạn chế là bạn không có cách nào để biết, trừ khi bạn thêm cơ chế đồng bộ/thông báo của riêng mình, khi tác vụ đã hoàn thành.

14

EndInvoke() có hành vi hữu ích nhưng ít được đề cập - nó trả về tất cả các ngoại lệ chưa được giải quyết mà đại biểu được tạo trong ngữ cảnh của chuỗi ban đầu để bạn có thể di chuyển logic xử lý ngoại lệ vào mã chính.

Ngoài ra, nếu đại biểu của bạn có tham số out/ref, chúng sẽ được thêm vào chữ ký EndInvoke() cho phép bạn lấy chúng khi phương thức hoàn thành thực thi.

+0

cảm ơn rất nhiều, tôi không biết rằng – endian

4

Nếu bạn gọi ThreadPool.QueueUserWorkItem, các ngoại lệ được nêu ra trong mục công việc sẽ được giải phóng trên luồng nền (trừ khi bạn bắt chúng một cách rõ ràng). Trong .Net 2 và cao hơn điều này sẽ chấm dứt AppDomain của bạn.

Nếu bạn gọi delegate.BeginInvoke() thì ngoại lệ sẽ được xếp hàng đợi để được ném lại khi EndInvoke() được gọi. Nếu bạn không bao giờ gọi EndInvoke(), thì các ngoại lệ về cơ bản là bộ nhớ 'bị rò rỉ' (như bất kỳ trạng thái nào khác không được giải phóng bởi hoạt động async).

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