Nie dzwonienie do Delegate.EndInvoke może spowodować wyciek pamięci… mit?

Było wiele dyskusji na ten temat i wszyscy zgadzają się, że należy zawsze dzwonić do Delegate.EndInvoke, aby zapobiec wyciekowi pamięci (nawet Jon Skeet to powiedział!).

Zawsze przestrzegałem tej wskazówki bez zadawania pytań, ale ostatnio zaimplementowałem własną klasę AsyncResult i zobaczyłem, że jedynym zasobem, który może wyciekać, jest AsyncWaitHandle.

(W rzeczywistości tak naprawdę nie wycieka, ponieważ rodzimy zasób używany przez WaitHandle jest hermetyzowany w SafeHandle, który ma Finalizer, ale zwiększy presję na kolejkę finalizacji garbage collectora. Mimo to dobra implementacja AsyncResult będzie inicjuj AsyncWaitHandle tylko na żądanie ...)

Najlepszym sposobem, aby dowiedzieć się, czy istnieje wyciek, jest wypróbowanie go:

Action a = delegate { };
while (true)
    a.BeginInvoke(null, null);

Uruchomiłem to przez chwilę, a pamięć pozostanie między 9-20 MB.

Porównajmy z nazwiskiem Delegate.EndInvoke:

Action a = delegate { };
while (true)
    a.BeginInvoke(ar => a.EndInvoke(ar), null);

Przy tym teście, pamięć gra pomiędzy 9-30 MG, dziwne co? (Prawdopodobnie dlatego, że wykonanie polecenia AsyncCallback zajmuje trochę więcej czasu, więc w Puli wątków będzie więcej delegowanych w kolejce)

Jak myślisz ... „Rozwalony mit”?

P.S. ThreadPool.QueueUserWorkItem jest o sto bardziej efektywny niż Delegate.BeginInvoke, lepiej go używać do wywołań ognia i zapomnienia.

questionAnswers(4)

yourAnswerToTheQuestion