Observar colección (enlazar a Datagid) - Error de subprocesamiento

Tengo la siguiente configuración:

public class Monitor
{
    public ObservableCollection<People> listOfPeople = new ObservableCollection<People>();


    public dosomework() {
        Thread t = new ThreadStart(longwork);
        t.Start();
    }

   public longwork() {
        listOfPeople.Add(new People());
        Thread.Sleep(10000);

   }

}

public class People : INotifyPropertyChanged
{
    int _age;
    public int Age
    {
        get { return _age; }
        set
        {
            _age = value;
            Notify("Age");
        }
    }
}

public class UI : Window
{
    Monitor md = new Monitor();
}

Quiero vincular una cuadrícula de datos a la colección observable (datagrid.ItemSource = md.listOfPeople), sin embargo, recibo un error de subprocesamiento. Además, si no hago el trabajo prolongado en un nuevo hilo, la interfaz de usuario solo se actualiza después de que finaliza la función de trabajo prolongado. Pensé que la encuadernación evitaría este problema.

Cualquier ayuda apreciada.

preguntado el 08 de noviembre de 11 a las 15:11

3 Respuestas

El enlace es simplemente "otro código que escucha los cambios", por lo que el subproceso sigue siendo un problema.

La solución habitual es agregar a la lista en el hilo de la interfaz de usuario, ya que es desde donde escuchará Grid, pero esto dará un rendimiento deficiente si se ejecuta para elementos individuales.

Lo mejor es agrupar las adiciones en una lista temporal que se ejecuta en el hilo de fondo y llamar a AddRange a intervalos (¿cada 100 elementos?) Para mover ese lote a la colección de IU para dar una mejor respuesta y una actualización regular de DataGrid.

respondido 08 nov., 11:20

Como lo mencionaron otros, si realiza algún trabajo en el hilo que no sea la interfaz de usuario, debe enviarlo al hilo de la interfaz de usuario para actualizar realmente cualquier elemento que esté vinculado a un elemento de la interfaz de usuario.

En su ejemplo, eso sería bastante fácil. Solo pasa el Dispatcher (msdn) de tu ventana a tu Monitor y utilícelo para enviar en consecuencia:

...
Monitor md = new Monitor(this.Dispatcher);
...
public Monitor(Dispatcher dispatcher)
{
     _dispatcher = dispatcher;
}
...
public longwork() {
    _dispatcher.BeginInvoke((Action)(()=>listOfPeople.Add(new People()));
    Thread.Sleep(10000);

}

Podrías llamar Dispatcher.Invoke en lugar de Dispatcher.BeginInvoke, pero si no le importa el resultado y quiere avanzar rápido, BeginInvoke es su amigo.

respondido 17 nov., 11:03

La cuadrícula de datos enlazada está suscrita al evento CollectionChanged. En mi experiencia, el evento CollectionChanged se genera en cualquier hilo que haya provocado el cambio de la colección. En este caso, no es el hilo de la interfaz de usuario. Dado que los elementos de la interfaz de usuario solo se pueden modificar desde el subproceso de la interfaz de usuario, y el evento se genera y se maneja en un subproceso que no es de la interfaz de usuario, obtendrá su "Error de subproceso".

Como se indicó anteriormente, una solución simple es modificar solo ObservableCollection desde el hilo de la interfaz de usuario.

Si usa WPF o Silverlight, todos los FrameworkElements tienen una propiedad Dispatcher que puede usar para realizar trabajo en el subproceso de la interfaz de usuario. Ver también: http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcherobject.aspx

respondido 08 nov., 11:20

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.