Tengo algunos problemas de subprocesamiento con una aplicación grande en la que estoy trabajando (obteniendo excepciones entre hilos). ¿Hay alguna manera de encontrar el nombre/id del subproceso en el que se creó un control en particular?¿Hay alguna manera de encontrar el hilo del propietario de un control?
El error se produce cuando intento agregar un nuevo control a la colección de control de mi control. Realmente no puedo crear una muestra pequeña y reproducible, así que lo describiré lo mejor que pueda.
Tengo un control principal que se encuentra en un formulario, llámalo _mainControl. En su constructor que se crea una instancia de otro control, algo así como
ChildControl _childControl = new ChildControl();
Ahora _childControl existe pero no agregarlo a la colección _mainControls todavía.
Eventualmente, _mainControl recibe una notificación de evento de que debo agregar el control. En el controlador de eventos puedo comprobar si this.InvokeRequired y si lo es, invoco el manejador, algo así como lo siguiente:
AddControlEventHander(...)
{
if(InvokeRequired)
{
BeginInvoke(new MethodInvoker(AddControlEventHander);
return;
}
Controls.Add(_childControl);
}
La excepción siempre se lanza a Controls.Add ("operación de la Cruz-hilo no válida: Control '_item' accedido desde un hilo que no sea el hilo en el que se creó ").
Ahora, lo que no entiendo es cómo esto es posible. Creé _childControl en el mismo hilo en el que se creó _mainControl. Cuando miro la ventana de subprocesos mientras estoy depurando, el nombre/id del subproceso actual es el mismo cuando llamo a Control.Add como cuando se agregó _childControl. Sin embargo, lo que más me confunde son las siguientes llamadas de _mainControl:
InvokeReuqired == false;
_childControl.InvokeRequired == false;
_childControl._item.InvokeRequired == true; //I made _item public just to try this and it returns true!
¿Cómo es eso posible? ¿Es posible que _childControl se cree en un hilo mientras sus hijos se crean de alguna manera en otro? Todos los hijos de _childControl se crean durante la inicialización, como normalmente se hace.
Si alguien tiene alguna sugerencia/sugerencia sobre lo que podría estar pasando, por favor hágamelo saber.
Gracias.
Editar:
En caso de que a alguien le interesa, me enteré de lo que estaba ocurriendo. Tenía curiosidad sobre cómo se puede crear un control en un subproceso y se crean los secundarios en otro subproceso, aunque el componente InitializeComponent se realizó en el mismo subproceso. Entonces, descubrí en qué subproceso se estaba creando el niño usando un código similar al que Charles sugirió a continuación. Una vez que lo supe, al menos sabía en qué hilo enfocarme. Luego rompí el evento OnHandleCreated del control infantil y encontré el problema.
Una cosa que no sabía era que el control se crea cuando el control se hace visible por primera vez, no cuando se crea. Entonces, un hilo que no poseía el control intentaba establecer su visibilidad como verdadera. Así que agregué un cheque para ver si InvokeRequired y pensé que eso sería suficiente. Sin embargo, algo que realmente no esperaba es que llamar a InvokeRequired creará el control si aún no se ha creado. Esto en efecto hace que el control se cree en el hilo incorrecto y siempre devuelve falso para InvokeRequired. Lo solucioné tocando la propiedad Manejar del control para que se cree antes de invocar InvokeRequired.
Gracias por la ayuda chicos :)
Gracias por la sugerencia. También descubrí que el inocente 'if (control.Handle! = Null) ...' en realidad crea el control en ese hilo. –
Vea mi respuesta aquí http://stackoverflow.com/questions/8331144/ensuring-that-child-controls-are-created-in-main-ui-thread/17054689#17054689 –