La diferencia entre Invoke y BeginInvoke es que la primera es sincrónica (espera la finalización) mientras que la última es asíncrona (tipo de disparar y olvidar). Sin embargo, ambos funcionan publicando un mensaje en el bucle de mensaje de UI que hará que el delegado se ejecute cuando llegue a ese mensaje.
La propiedad InvokeRequired determina si necesita invocar o si ya está en el hilo correcto, no si desea realizar llamadas sincrónicas o asíncronas. Si InvokeRequired es falso, usted (en teoría) ya se está ejecutando en el hilo de la interfaz de usuario y simplemente puede realizar acciones síncronas directamente (o aún BeginInvoke si necesita desactivarlas de forma asincrónica). Esto también significa que no puede usar Invoke si InvokeRequired es falso, porque no hay forma de que el bucle de mensajes en el hilo actual continúe. Ese es un gran problema con su código anterior, pero no necesariamente el error que está informando. Usted puede realmente utilizar BeginInvoke en cualquier caso, si tiene cuidado con la invocación recursiva, y así sucesivamente.
Sin embargo, no puede usar ninguna de ellas sin un asa de ventana. Si el Form/Control se ha instanciado pero no se ha inicializado (es decir, antes de que se muestre por primera vez), es posible que aún no tenga un identificador. Y el identificador se elimina mediante Dispose(), como después de cerrar el formulario. En cualquier caso, InvokeRequired devolverá falso porque no es posible invocar sin un identificador. Puede marcar IsDisposed, y también hay una propiedad IsHandleCreated que prueba más específicamente si existe el identificador. Por lo general, si IsDisposed es verdadero (o si IsHandleCreated es falso), quiere ingresar en un caso especial, como simplemente descartar la acción como no aplicable.
Por lo tanto, el código que desea es probablemente más como:
if (IsHandleCreated)
{
// Always asynchronous, even on the UI thread already. (Don't let it loop back here!)
BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount);
return; // Fired-off asynchronously; let the current thread continue.
// WriteToForm will be called on the UI thread at some point in the near future.
}
else
{
// Handle the error case, or do nothing.
}
O tal vez:
if (IsHandleCreated)
{
// Always synchronous. (But you must watch out for cross-threading deadlocks!)
if (InvokeRequired)
Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount);
else
WriteToForm(finished, numCount); // Call the method (or delegate) directly.
// Execution continues from here only once WriteToForm has completed and returned.
}
else
{
// Handle the error case, or do nothing.
}
Sin saber más sobre el problema, suena como que está invocando un evento antes de que su forma está totalmente creado/inicializado, o en otro hilo en algún punto en el que no deben' t ser –
Si tiene temporizadores en ejecución (System.Timers o System.Threading), compruebe si están causando que este código se ejecute en un formulario que no se ha construido completamente o está Disposed. –
¿Dónde está este código, qué método o controlador de eventos? – Kev