c# - ¿EndInvoke() es opcional, opcional o definitivamente no opcional?
multithreading delegates (7)
He leído opiniones contradictorias sobre si cada BeginInvoke () tiene que coincidir con un EndInvoke (). ¿Hay alguna fuga u otros problemas asociados con NO llamar a EndInvoke ()?
Cada respuesta en esta publicación dice que EndInvoke () no es opcional. Sin embargo, encontré el siguiente comentario altamente calificado que es la respuesta aceptada en este hilo SO:
"Tenga en cuenta que el equipo de Windows Forms ha garantizado que puede usar Control.BeginInvoke de una manera ''disparar y olvidarse'', es decir, sin llamar a EndInvoke. Esto no ocurre con las llamadas asincrónicas en general: normalmente cada BeginXXX debe tener una llamada EndXXX correspondiente. , por lo general en la devolución de llamada ".
Delegate.EndInvoke está documentado como si así lo llamaras (es decir, es necesario, se producen otras filtraciones) desde msdn :
Nota IMPORTANTE
Independientemente de la técnica que utilice, llame siempre a EndInvoke para completar su llamada asincrónica.
Control.EndInvoke está bien para ignorar los métodos de "olvida y olvida", de msdn :
Puede llamar a EndInvoke para recuperar el valor de retorno del delegado, si es necesario, pero esto no es necesario.
Sin embargo, si está utilizando Delegate.BeginInvoke
y no desea el resultado, considere usar ThreadPool.QueueUserWorkItem
en ThreadPool.QueueUserWorkItem
lugar, le facilitará la vida y evitará el dolor de IAsyncResult
etc.
EndInvoke no es opcional porque es el lugar donde se lanzan las excepciones si algo salió mal en el procesamiento asincronous.
De todos modos, no debería haber ninguna fuga porque si IAsyncResult contiene algún recurso nativo, debería implementar correctamente IDisposable y disponer de dichos recursos cuando el GC llame a su finalizador.
EndInvoke no es opcional.
Más información here
Es solo opcional si no le importa que la memoria de su programa crezca mucho. El problema es que el GC se mantiene en todas las referencias en su hilo, porque es posible que desee llamar a EndInvoke en algún momento. Me gustaría ir con la respuesta de Marc, el grupo de temas te hará la vida más fácil. Sin embargo, debes tener cuidado si generas hilos de tus hilos, ya que está limitado en la cantidad de hilos que puede girar.
No es opcional porque llamar a BeginInvoke utiliza un WaitHandle que, a su vez, hace uso de un objeto kernel que mantiene un recuento de cuántas referencias se necesitan. Llamar a EndInvoke descarta con gracia el identificador que disminuye ese contador en el objeto kernel y cuando ese conteo llega a cero, el administrador de objetos del kernel lo destruirá.
Y la llamada a EndInvoke no es una llamada opcional, es una parte del contrato. Si llama a BeginInvoke, debe llamar a EndInvoke.
Ejemplo clásico de por qué esto es necesario. Es muy posible que IAsyncResult devuelto por BeginInvoke haya asignado recursos asociados. Más comúnmente es una especie de WaitHandle. Como IAsyncResult no implementa IDisposable, se debe elegir otro lugar para liberar los recursos. El único lugar para hacerlo es EndInvoke.
Discuto brevemente este problema en la siguiente publicación del blog.
http://blogs.msdn.com/jaredpar/archive/2008/01/07/isynchronizeinvoke-now.aspx