winforms - traves - la evaluación de la función requiere que se ejecuten todos los subprocesos.
Winforms vinculante de datos para objetos comerciales en un escenario de subprocesos múltiples sin InvokeRequired? (1)
Esto no responde a su pregunta, pero trato de evitar este problema en la medida de lo posible.
Debido a la existencia de enlace de datos, me aseguro de que el único código que puede actualizar los objetos comerciales es el código que se ejecuta en el hilo de la GUI.
Para las operaciones de sincronización, adopto un patrón de:
- Enviar trabajo a segundo plano: active una operación asíncrona, por ejemplo, un elemento del grupo de subprocesos, desde el subproceso de GUI. Pasar solo tipos de datos simples en el grupo de subprocesos y recibir solo tipos de datos simples. Si el grupo de subprocesos utiliza objetos comerciales, asegúrese de que sean nuevos (que aún no se hayan enlazado a los datos) o que sean clones de los originales (para evitar el acceso concurrente).
- Haga el trabajo y obtenga un resultado: ejecute la operación asincrónica en una cadena de fondo. El código de hilo de fondo poseerá los objetos ''seguros'' que le da la GUI; no tendrá ninguna interacción con el resto de la aplicación.
- Desempaquete el resultado en la GUI: cuando finaliza la operación de sincronización, desencadena un evento ''Estoy completo'' en el hilo de la GUI. En respuesta, el hilo de la GUI puede desempaquetar cualquier resultado de la operación en segundo plano y fusionarlos de nuevo en los objetos comerciales principales, con la seguridad de que no se tratará con el acceso concurrente.
Puedo recomendar la clase System.Threading.Tasks.Task
como una abstracción en la mayoría de los pasos anteriores. Es nuevo en .NET 4.0, pero también está disponible como descarga separada para las aplicaciones .NET 3.5.
Los pasos (1) y (2) son lo que hace la clase Task
sin ninguna personalización. Puede lograr (3) al generar una Task
separada desde dentro del hilo de fondo y especificando TaskScheduler.FromCurrentSynchronizationContext
como un programador. (Deberá llamar a FromCurrentSynchronizationContext
desde el hilo de la GUI, en el paso (1), no desde el hilo de fondo).
Por ejemplo, tengo un objeto comercial Person
:
class Person : INotifyPropertyChanged
{
string Name { get; set; }
DateTime DateOfBirth { get; set; }
}
// ^ abbreviated for better legibility; implementation would be trivial
Y tengo algunos controles de UI de Winforms vinculados a datos para un objeto de esta clase:
Person somePerson = ...;
nameTextBox.DataBindings.Add("Text", somePerson, "Name");
dobDatePicker.DataBindings.Add("Value", somePerson, "DateOfBirth");
Ahora estoy haciendo cambios en somePerson
y gracias a tener INotifyPropertyChanged
implementado, esos cambios se reflejan en la IU. Hasta aquí todo bien.
Ahora a mi problema: si realizo cambios a somePerson
en un hilo de trabajo (es decir, no en el hilo de UI), por ejemplo, porque estoy cargando datos de un DB como operación en segundo plano, esto podría causar excepciones porque el enlace de datos intenta actualizar los controles, lo cual solo está permitido en el hilo de UI.
Esto significa que tengo que llamar a InvokeRequired
en un elemento de IU para ver si puedo actualizar un objeto comercial, lo que parece una violación de las capas lógicas de la aplicación .
Idealmente, quiero poder modificar mis objetos comerciales sin tener que preocuparme si está relacionado con datos a la UI o no. ¿Es esto de alguna manera posible con el enlace de datos de Winforms, o no?