8

Ich habe ein benutzerdefiniertes Objekt, das INotifyPropertyChanged implementiert. Ich habe eine Auflistung dieser Objekte, wobei die Auflistung auf BindingList basiert Ich habe eine Bindungsquelle für die Auflistung erstellt und legen Sie die Datenquellen der Bindungsquelle und Datagridview fest.Wie aktualisiere ich eine datengebundene Datagridview von einem Hintergrund Thread

Alles funktioniert gut, außer dass ich Eigenschaften für das benutzerdefinierte Objekt aus Hintergrundthreads aktualisieren muss. Wenn ich dies tue, erhalte ich den folgenden Fehler:

BindingSource kann keine eigene Datenquelle sein. setzen Sie nicht die Datasource und Datamember Eigenschaften auf Werte, den Binding

refere zurück fand ich den folgenden Beitrag, dass mein genaues Problem scheint (und Lösung?) zu haben, aber ich kann es nicht ganz herausfinden. Ich habe die beiden Event-Funktionen in meiner Sammlung Klasse

http://social.msdn.microsoft.com/forums/en-US/winformsdatacontrols/thread/3566f7c7-eb47-422e-ab09-9549a18da360/

I erstellt und initialisiert die oper Variablen pro der Post in meinem Business-Objekt, und dann. Dies kompiliert korrekt, aber hängt ohne Ausnahme beim Ausführen.

Ich habe viele Posts gesehen zu verwenden Invoke/Begin Invoke, aber ich rufe keine Funktionen auf der Benutzeroberfläche, nur Business-Objekte aktualisieren, so dass ich nicht sicher bin, wo ich die Aufrufe aufrufen würde.

Eine Einschränkung: Ich möchte, dass das Geschäftsobjekt nicht darüber informiert, wer es anzeigt (da mehrere Benutzer vorhanden sind). Daher werden GUI-Verweise in das Geschäftsobjekt gesendet, damit ich später mit diesen Verweisen aufrufen kann eine Option.

Antwort

14

Ich fand diese Klasse in einem Forum, das funktioniert. verwenden diese nur statt Binding

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

using System.ComponentModel; 
using System.Threading; 

namespace Utility 
{ 
    public class ThreadedBindingList<T> : BindingList<T> 
    { 
     SynchronizationContext ctx = SynchronizationContext.Current; 

     protected override void OnAddingNew(AddingNewEventArgs e) 
     { 

      if (ctx == null) 
      { 
       BaseAddingNew(e); 
      } 
      else 
      { 
       ctx.Send(delegate 
       { 
        BaseAddingNew(e); 
       }, null); 
      } 
     } 
     void BaseAddingNew(AddingNewEventArgs e) 
     { 
      base.OnAddingNew(e); 
     } 
     protected override void OnListChanged(ListChangedEventArgs e) 
     { 
      // SynchronizationContext ctx = SynchronizationContext.Current; 
      if (ctx == null) 
      { 
       BaseListChanged(e); 
      } 
      else 
      { 
       ctx.Send(delegate 
       { 
        BaseListChanged(e); 
       }, null); 
      } 
     } 
     void BaseListChanged(ListChangedEventArgs e) 
     { 
      base.OnListChanged(e); 
     } 
    } 
} 
+0

@Marc Gravell [Ich weiß, der Beitrag ist alt, aber ..Wenn aus einer anderen Liste ThreadedBindingList (meine List) instanziiert - es gibt keine Methode dafür. Sollte die Methode nicht vorhanden sein, damit diese "vollständig" ist oder gibt es ein Threading-Problem? – Stix

1

Da ich die Zeit genommen, um die Probe für meine Bedürfnisse zu formatieren könnte ich auch sie werden hier als eine lesbare Referenz. Bis auf die Formatierung hat sich nichts geändert.

using System.ComponentModel; 
using System.Threading; 

namespace Utility 
{ 
    public class ThreadedBindingList : BindingList 
    { 
    SynchronizationContext ctx = SynchronizationContext.Current; 
    protected override void OnAddingNew(AddingNewEventArgs e) 
    { 
     if (ctx == null) 
     { 
     BaseAddingNew(e); 
     } 
     else 
     { 
     ctx.Send(delegate { BaseAddingNew(e); }, null); 
     } 
    } 

    void BaseAddingNew(AddingNewEventArgs e) 
    { 
     base.OnAddingNew(e); 
    } 

    protected override void OnListChanged(ListChangedEventArgs e) 
    { 
     // SynchronizationContext ctx = SynchronizationContext.Current; 
     if (ctx == null) 
     { 
     BaseListChanged(e); 
     } 
     else 
     { 
     ctx.Send(delegate { BaseListChanged(e); }, null); 
     } 
    } 

    void BaseListChanged(ListChangedEventArgs e) 
    { 
     base.OnListChanged(e); 
    } 
    } 
} 
0

Nicht ganz Thread-sicher, aber diese kleine Änderung der oben genannten Antworten könnte einen großen Einfluss haben, wenn Ihr Hintergrund-Thread-Objekt-Eigenschaften zu modifizieren ist schneller, als sie angezeigt werden kann;

protected override void OnListChanged(ListChangedEventArgs e) 
{ 
    // SynchronizationContext ctx = SynchronizationContext.Current; 
    if (ctx == null) 
    { 
    BaseListChanged(e); 
    } 
    else if(e.ListChangedType == ListChangedType.ItemChanged) 
    { 
    ctx.Post(delegate { BaseListChanged(e); }, null); 
    } 
    else 
    { 
    ctx.Send(delegate { BaseListChanged(e); }, null); 
    } 
} 

Willkommen Vorschläge für die Anzahl der entsandten Anrufe zu reduzieren, wenn das gleiche Objekt mehr als einmal geändert worden, und sicherstellen, dass jeder späteren Anruf senden blockiert, bis alle gebucht Anrufe bearbeitet wurden.

Verwandte Themen