EndInvoke () è facoltativo, sort-of opzionale o sicuramente non facoltativo?

Ho letto opinioni contrastanti sul fatto che a ogni BeginInvoke () debba corrispondere un EndInvoke (). Ci sono perdite o altri problemi associati a NOT che chiama EndInvoke ()?

Delegate.EndInvoke è documentato come si chiamerà questo (cioè necessario, altrimenti si verificano perdite) da msdn :

Nota importante

Indipendentemente dalla tecnica utilizzata, chiama sempre EndInvoke per completare la chiamata asincrona.

Control.EndInvoke può ignorare i metodi fire-and-forget – da msdn :

È ansible chiamare EndInvoke per recuperare il valore restituito dal delegato, se necessario, ma non è necessario.

Tuttavia, se si utilizza Delegate.BeginInvoke e non si desidera ottenere il risultato, prendere in considerazione l’utilizzo di ThreadPool.QueueUserWorkItem anziché – renderà la vita molto più semplice ed eviterà il dolore di IAsyncResult ecc.

EndInvoke non è facoltativo.

Maggiori informazioni qui

E la chiamata EndInvoke non è una chiamata opzionale, è una parte del contratto. Se chiami BeginInvoke, devi chiamare EndInvoke.

Esempio classico del perché è necessario. È molto probabile che IAsyncResult restituito da BeginInvoke abbia assegnato risorse ad esso associate. Più comunemente un WaitHandle di sorta. Poiché IAsyncResult non implementa IDisposable, è necessario scegliere un altro posto per liberare le risorse. L’unico posto per farlo è EndInvoke.

Discuto brevemente di questo problema nel seguente post del blog.

http://blogs.msdn.com/jaredpar/archive/2008/01/07/isynchronizeinvoke-now.aspx

EndInvoke non è opzionale perché è il luogo in cui vengono generate eccezioni se qualcosa è andato storto nell’elaborazione asincrona.

In ogni caso non ci dovrebbero essere perdite perché se IAsyncResult è in possesso di qualche risorsa nativa dovrebbe implementare correttamente IDisposable e disporre tali risorse quando il GC chiama il suo finalizzatore.

Non è opzionale perché chiamare BeginInvoke fa uso di un WaitHandle che a sua volta utilizza un object kernel che mantiene un conteggio per il numero di riferimenti necessari. La chiamata EndInvoke elimina con garbo l’handle che decrementa quel contatore sull’object kernel e quando tale conteggio raggiunge lo zero, il gestore oggetti del kernel lo distruggerà.

È solo opzionale se non ti dispiace che la memoria del tuo programma cresca molto. Il problema è che il GC trattiene tutti i riferimenti nel tuo thread, perché potresti voler chiamare EndInvoke ad un certo punto. Vorrei andare con la risposta di Marc, il threadpool renderà la vita più facile. Tuttavia, è necessario prestare attenzione se si generano i thread dai thread, in quanto è limitato dal numero di thread che può far ruotare.

Ogni risposta in questo post dice che EndInvoke () non è facoltativo. Tuttavia, ho trovato il seguente commento altamente classificato che è la risposta accettata su questo thread SO:

“Notare che il team di Windows Form ha garantito che è ansible utilizzare Control.BeginInvoke in modo” ignora e dimentica “, vale a dire senza chiamare EndInvoke. Ciò non vale per le chiamate asincrone in genere: normalmente ogni BeginXXX deve avere una chiamata EndXXX corrispondente , di solito nel callback. ”

Qual è la differenza tra Invoke () e BeginInvoke ()