Pregunta

En una aplicación que estoy trabajando, miles de actualizaciones están siendo recibidos por segundo.Como reflejo de estas actualizaciones en la interfaz de usuario de inmediato y uno por uno es el rendimiento de una exageración.

El siguiente código rendimientos muy mal rendimiento, debido a que el manejo de cada actualización requiere invocar el subproceso de interfaz de usuario y la adición de un nuevo elemento a una ObservableCollection que a su vez desencadena la CollectionChanged evento.

foreach (var update in updates.GetConsumingEnumerable())
{
    // Handle Update
}

Lo que estoy tratando de hacer es hacer que el consumidor espere un poco de tiempo (es decir,50 milisegundos) para dar una oportunidad al editor para añadir más elementos, y luego manejar estas actualizaciones en trozos.

Actualmente, estoy usando el siguiente código, pero me resulta difícil de predecir por cuánto tiempo los elementos de la estancia en la colección antes de ser consumido, me temo que este enfoque puede producir otro cuello de botella de rendimiento.

List<Tuple<T, List<string>>> updatesToHandle = new List<Tuple<T, List<string>>>();
while (!updates.IsAddingCompleted)
{
    Tuple<T, List<string>> item = null;
    if (updates.TryTake(out item, 5)) // Try Take for 5 Milliseconds
    {
        updatesToHandle.Add(item);
    }
    else
    {
        var newItems = new List<T>(updatesToHandle.Count);
        var updatedItems = new List<Tuple<T, List<string>>>(updatesToHandle.Count);
        foreach (var update in updatesToHandle)
        {
            try
            {
                // Handle Update
            }
            finally
            {
                updatesToHandle.Clear();
                Thread.Sleep(50);
            }
        }
    }
}
¿Fue útil?

Solución

Consideraría usar extensiones reactivas reactiveexensions .Este enlace resuelve un problema similar Ejemplo de compra de acciones

Otros consejos

Yo sugeriría dos cambios en el código.

En primer lugar, en lugar de tener el hilo del sueño, crear un temporizador que se activa cada 50 milisegundos.Que el temporizador controlador de lazo en TryTake sin demora, recogiendo todos los objetos que están en la colección (o hasta algún máximo).Sin demora, TryTake va a regresar de inmediato si la colección está vacía.

Segundo, no llame a la "actualización de la interfaz de usuario de" una vez por cada actualización.Modificar el controlador de actualización para que acepte la lista completa de actualizaciones en lugar de una actualización en un momento.A fin de evitar el tiempo de espera para el subproceso de interfaz de usuario.

Lo anterior supone, por supuesto, que ha modificado su controlador de actualización, de modo que puede agregar varios elementos a la ObservableCollection en una sola toma, la prevención de múltiples CollectionChanged eventos.

i Segundo Rx.Específicamente, usted desea bufferbytime (si se agrega cuando la velocidad de entrada es alta) o el acelerador (si se desecha los valores cuando la tasa de entrada es demasiado alta).Además, su UI probablemente debería estar obligada a los comportamientos, que siempre almacenará el último valor para que los nuevos suscriptores obtengan ese último valor en caché inmediatamente cuando se suscriban.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top