Đã có rất nhiều cuộc thảo luận xung quanh việc này và mọi người đều đồng ý rằng bạn nên luôn luôn gọi Delegate.EndInvoke để ngăn chặn rò rỉ bộ nhớ (thậm chí Jon Skeet đã nói nó!).Không gọi Delegate.EndInvoke có thể gây rò rỉ bộ nhớ ... một huyền thoại?
Tôi luôn làm theo hướng dẫn này mà không cần đặt câu hỏi, nhưng gần đây tôi đã triển khai lớp AsyncResult của riêng mình và thấy rằng tài nguyên duy nhất có thể bị rò rỉ là AsyncWaitHandle.
(Thực tế nó không thực sự bị rò rỉ vì tài nguyên gốc được sử dụng bởi WaitHandle được đóng gói trong một SafeHandle trong đó có một Finalizer, nó sẽ thêm áp lực vào hàng đợi cuối cùng của bộ thu gom rác mặc dù vậy. thực hiện asyncResult sẽ chỉ khởi tạo AsyncWaitHandle theo yêu cầu ...)
cách tốt nhất để biết nếu có một sự rò rỉ chỉ là để thử nó:
Action a = delegate { };
while (true)
a.BeginInvoke(null, null);
tôi chạy này trong một thời gian và bộ nhớ duy trì từ 9-20 MB.
Hãy so sánh với khi Delegate.EndInvoke được gọi là:
Action a = delegate { };
while (true)
a.BeginInvoke(ar => a.EndInvoke(ar), null);
Với xét nghiệm này, vở kịch nhớ giữa 9-30 MG, lạ eh? (Có thể vì mất nhiều thời gian hơn để thực thi khi có AsyncCallback, do đó sẽ có nhiều đại biểu được xếp hàng đợi hơn trong ThreadPool)
Bạn nghĩ gì ... "Huyền thoại bị bẻ khóa"?
P.S. ThreadPool.QueueUserWorkItem là một trăm hiệu quả hơn so với Delegate.BeginInvoke, tốt hơn để sử dụng nó cho lửa & quên cuộc gọi.
Câu hỏi hay! +1. BTW, bạn xem quá nhiều MythBusters;) – RCIX
Tôi đồng ý, ThreadPool.QueueUserWorkItem là một phương pháp tuyệt vời và không được sử dụng. – Anton