puede llamar c# winforms

c# - llamar - invoke begininvoke



No se puede invocar Invoke o BeginInvoke en un control hasta que se haya creado el identificador de ventana (6)

Obtengo la siguiente excepción:

No se puede invocar Invoke o BeginInvoke en un control hasta que se haya creado el identificador de ventana.

Este es mi código:

if (InvokeRequired) { BeginInvoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount); } else Invoke(new UpdateTextFieldDelegate(WriteToForm), finished, numCount);

Encontré páginas sobre este tema en este sitio, pero no sé qué está mal.


Esto ocurrirá normalmente en escenarios de subprocesos múltiples en los que alguna fuente externa (tal vez un NetworkStream) inserta datos en un formulario antes de que el formulario se haya inicializado correctamente.

El mensaje también puede aparecer después de que se elimine un formulario.

Puede verificar IsHandleCreated para ver si ya se ha creado un formulario, pero necesita poner todo en el manejo adecuado de errores, ya que la instrucción Invoke puede generar una excepción si intenta actualizar su formulario mientras se está cerrando la aplicación.


La diferencia entre Invoke y BeginInvoke es que el primero es sincrónico (espera su finalización) mientras que el último es asíncrono (una especie de disparar y olvidar). Sin embargo, ambos funcionan mediante la publicación de un mensaje en el bucle de mensajes de IU 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 subproceso correcto, no si desea realizar llamadas síncronas o asíncronas. Si InvokeRequired es falso, (en teoría) ya se está ejecutando en el subproceso de la interfaz de usuario y simplemente puede realizar acciones síncronas directamente (o aún BeginInvoke) si necesita despedirlos de forma asíncrona. Esto también significa que no puede usar Invocar 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. Puede usar BeginInvoke en cualquier caso, si está atento a la invocación recursiva, y así sucesivamente.

Sin embargo, no puede utilizar ninguno de los dos sin un identificador de ventana. Si el formulario / control se ha creado una instancia 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 despeja con Dispose (), por ejemplo, después de cerrar el formulario. En cualquier caso, InvokeRequired devolverá false porque no es posible invocar sin un manejador. Puede verificar IsDisposed, y también hay una propiedad IsHandleCreated que, más específicamente, comprueba si existe el identificador. Por lo general, si IsDisposed es verdadero (o si IsHandleCreated es falso), desea apostar en un caso especial, como simplemente descartar la acción como no aplicable.

Entonces, el código que quieres 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. }


Probablemente esté llamando a esto en el constructor del formulario, en ese punto el identificador de la ventana del sistema subyacente aún no existe.


Si va a usar un control de otro hilo antes de mostrar el control o hacer otras cosas con el control, considere forzar la creación de su identificador dentro del constructor. Esto se hace usando la función CreateHandle . En un proyecto de subprocesos múltiples, donde la lógica del "controlador" no está en un WinForm, esta función es instrumental para evitar este tipo de errores.



aqui esta mi respuesta

Supongamos que desea escribir "Hola mundo" en un cuadro de texto. Luego, si utiliza "Ishandlecreated", su operación no se realizará si aún no se han creado los controladores. Por lo tanto, debe forzarse a CreateHandlers si aún no se ha creado.

Aqui esta mi codigo

if (!IsHandleCreated) this.CreateControl(); this.Invoke((MethodInvoker)delegate { cmbEmail.Text = null; });