2012-03-06 47 views
5

Tengo un Asynchronous BindingList que contiene objetos que se manipulan en un subproceso de trabajo y se vinculan a un BindingSource en el subproceso de la IU principal con un BindingSource vinculado a un DataGridView.Ubicación de objetos en BindingList

¿Hay alguna posibilidad de localizar objetos en mi BindingList sin recorrer la lista?

Miré debajo del capó de LINQ y básicamente es un bucle foreach recubierto de azúcar. También entiendo si implemento IBindingList.Find() no es más que un for-loop ...

He "intentado" sincronizar/asignar mi BindingList a un diccionario que refleja mi BindingList y utiliza el diccionario localizar objetos y pasar los resultados (índice) a mi BindingList pero esto no está funcionando porque hay demasiada adición y eliminación de los objetos y no puedo mantener las cosas organizadas.

Esta es una aplicación de alto rendimiento que trata con datos de alta frecuencia en tiempo real del mercado de valores. Es por eso que no puedo iterar a través de BindingList, es demasiado ineficiente.

¿Puede alguien darme algunos consejos y/o soluciones?

Respuesta

5

Así que un tipo de lista de enlaces de búsqueda rápida ... Aquí hay uno que preparé antes.

Este es el enfoque 'sincronizar/asignar' al que se refiere. Lo he usado antes para datos rápidos, donde el cuello de botella principal buscaba elementos en la lista. Creo que he cubierto todos los métodos necesarios para mantenerme sincronizado u 'organizado'. Puede agregar una prueba para AddRange: no tengo un decompilador a mano, no estoy seguro si solo llama a InsertItem.

Obviamente, aquí tiene un compromiso directo de mayor uso de memoria e tiempo de inserción, manteniendo dos listas, pero para datos de marcación rápida, que normalmente es una solución aceptable para tiempos de búsqueda mejorados.

Utilice la clase como lo haría con un BindingList, pero cuando necesite buscar un elemento rápidamente, utilice el método FastFind.

public class FastLookupBindingList<TKey, TVal> : BindingList<TVal> 
{ 
    private readonly IDictionary<TKey, TVal> _dict = new Dictionary<TKey, TVal>(); 
    private readonly Func<TVal, TKey> _keyFunc; 

    public FastLookupBindingList(Func<TVal, TKey> keyFunc) 
    { 
     _keyFunc = keyFunc; 
    } 

    public FastLookupBindingList(Func<TVal, TKey> keyFunc, IList<TVal> sourceList) : base(sourceList) 
    { 
     _keyFunc = keyFunc; 

     foreach (var item in sourceList) 
     { 
      var key = _keyFunc(item); 
      _dict.Add(key, item); 
     } 
    } 

    public TVal FastFind(TKey key) 
    { 
     TVal val; 
     _dict.TryGetValue(key, out val); 
     return val; 
    } 

    protected override void InsertItem(int index, TVal val) 
    { 
     _dict.Add(_keyFunc(val), val); 
     base.InsertItem(index, val); 
    } 

    protected override void SetItem(int index, TVal val) 
    { 
     var key = _keyFunc(val); 
     _dict[key] = val; 

     base.SetItem(index, val); 
    } 

    protected override void RemoveItem(int index) 
    { 
     var item = this[index]; 
     var key = _keyFunc(item); 
     _dict.Remove(key); 

     base.RemoveItem(index); 
    } 

    protected override void ClearItems() 
    { 
     _dict.Clear(); 
     base.ClearItems(); 
    } 
} 

Uso:

public class Person 
    { 
     public int Id { get; set; } 
     public string Name { get; set; } 
    } 

    private void simpleButton1_Click(object sender, EventArgs e) 
    { 
     var keyedBindingList = new FastLookupBindingList<int, Person>(p => p.Id) 
            { 
             new Person {Id = 1, Name = "Joe"}, 
             new Person {Id = 2, Name = "Josephine"} 
            }; 
     var person = keyedBindingList.FastFind(2); 
     var unkonwn = keyedBindingList.FastFind(4); 
    } 
+0

THX stevenP! Nunca vi tu solución. Voy a implementar esto ahora y ver cómo funciona. se ve bien sin embargo, y esto es lo que estaba intentando hacer antes, pero no pude conseguir la sincronización en su lugar. –

+0

¿Cómo harías que este threadsafe. Tenemos el mismo caso de uso donde un hilo de fondo actualiza la lista de enlaces indexada. Sin embargo, el uso de su implementación causa problemas de sincronización. Agregar bloqueo en todas partes, perjudica el rendimiento también. – Rik

+0

¿Se puede usar ISynchronizeInvoke.Invoke para hacer sus actualizaciones? Es decir, utilice el trabajador en segundo plano para realizar la tarea de larga ejecución de recuperar/manipular sus datos, y cuando esté listo, llame a Invoke para obtener el hilo de la interfaz de usuario y actualizar BindingList. –