2012-04-14 6 views
2

Ich habe ein DevExpress GridControl an eine BindingList gebunden.Benötigen Sie eine Erklärung zur Lebensdauer von Objekten, die in einem Thread erstellt wurden

Ich versuchte, das Binding aus einem Thread und dies hat eine Ausnahme, ich gegoogelt, ihn zu ändern und fand die folgende Erklärung:

Dieses Problem mit dem XtraGrid nicht direkt verbunden. Leider können Sie die Datenquelle des Gitters nicht in einem Hintergrundthread ändern, da dies zu vielen Problemen bei der Synchronisierung führen wird. Das XtraGrid kann einige Operationen mit der zugrunde liegenden Datenquelle zur gleichen Zeit ausführen, wie Ihr Hintergrund-Thread es ändert. In diesem Fall empfängt das Grid möglicherweise später eine Änderungsbenachrichtigung und versucht, Zeilen aus der Datenquelle zu aktualisieren, die das genannte Problem verursachen. Dieses Problem kann in vielen Fällen auftreten. Wenn ein Benutzer beispielsweise Daten bearbeitet, gruppiert er sie oder das XtraGrid versucht, die Zusammenfassungen neu zu berechnen. Die einzige Lösung für dieses Problem besteht darin, die DataSource-Referenz des Rasters innerhalb eines Hintergrundthreads zu ändern (HINWEIS: Sie müssen es mithilfe der Invoke-Methode implementieren). Anders ausgedrückt, sollten Sie innerhalb eines Hintergrund-Threads mit einer lokalen Kopie der DataSource arbeiten und ihren Klon bei Bedarf an die DataSource des Grids übergeben. Im beigefügten Beispiel finden Sie ein Beispielprojekt, das diesen Ansatz demonstriert.

Ich habe versucht, was es sagte, in dieser resultierenden:

proxyWorker = new Thread(() => 
{ 
    //Clone the datasource into the thread 
    BindingList<Proxy> newList = new BindingList<Proxy>(proxies); 

    //Set the proxy source to the cloned datasource in the thread 
    gcProxies.BeginInvoke(new MethodInvoker(delegate { gcProxies.DataSource = newList; })); 

    //Logic here 
}); 

proxyWorker.Name = "proxyTester"; 

proxyWorker.Start(); 

Es funktioniert, aber was ich nicht verstehe ist, was nach den Fadenenden auf die Datenquelle passiert? Ist nicht newList zerstört?

Was ich dachte, ist am Ende, dass ich newList es reklonieren und zurück in proxies (die Original-Datenquelle)

+1

Bitte geben Sie einen Titel, der Ihre Frage zusammenfasst. –

+0

Behoben, sorry, dass vergessen wurde, es richtig einzustellen. – TheGateKeeper

Antwort

3

Ich denke, deine Verwirrung rührt von der Tatsache her, dass du denkst, dass ein .NET-Objekt mit dem Thread verknüpft ist, der es erstellt hat. Das ist nicht der Fall, alle Threads in einem Prozess teilen sich den gleichen GC-Heap. Eine Liste <> Objekt in einem Thread erstellt unterscheidet sich nicht von einer Liste <> in einem anderen, es behält in keiner Weise den Thread, der es erstellt am Leben.

Was ist ein Problem mit Threading ist, dass es viele Klassen gibt, die nicht Thread-sicher sind.Dies ist sicherlich für jede UI-Komponente der Fall. Was Sie nicht können Do ist eine Eigenschaft eines solchen Klassenobjekts aus einem anderen Thread zuweisen, während dieser Eigenschaftswert auch im UI-Thread verwendet werden kann. Fast alle Eigenschaften einer UI-Komponente haben diese Einschränkung. Besonders problematisch ist die Datenbindung, da die Eigenschaftszuordnungen nicht direkt sichtbar sind. Sie legen nur die DataSource und nicht alle anderen Eigenschaften fest, die die Bindung festlegt. Die Verwendung von Control.BeginInvoke oder Dispatcher.BeginInvoke stellt sicher, dass die Eigenschaftswerte in demselben Thread festgelegt werden, der das Steuerelement erstellt hat, wodurch das Threadsicherheitsproblem gelöst wird.

+0

Was ich am Ende getan habe, war, das gebundene Objekt in den Thread zu klonen und es am Ende wieder an die ursprüngliche Quelle zu klonen. Funktioniert super! – TheGateKeeper

2

, die ‚eins zu eins‘ C# Garbage Collection,

new list Leben ist los ist durch die gcProxies.DataSource verwiesen.

Bis Sie keine Referenzen mehr auf diese Liste haben, sind Sie gut.

Wenn es keine spezifischen 'cross-thread' Bedenken in Bezug auf die 'Liste' gibt, greifen Sie auf cross thread oder erstellen in einem und verwenden in einem anderen - alles wird einfach gut funktionieren.
Hier werden Sie nur initialisiert und verwenden Sie es nie wieder anders als durch DataSource, so ist alles in Ordnung.

hoffte, das hilft

EDIT: auf den Kommentare zu antworten, ich bin ein bisschen

Thema vereinfacht Sie übrigens auf dem Objekt erstellt, hat nichts mit dem Objekt „Lebenszyklus“ zu tun - dh Thread besitzt das Objekt nicht. Die Anwendungsdomäne tut dies (was außerhalb des Gültigkeitsbereichs liegt), aber Sie können Threadgrenzen "kreuzen" oder tun, was Sie wollen - aber Sie müssen nur Ihren Code/Ihre Objekte synchronisieren.

+0

Ich benutze es wieder in einem anderen Teil des Programms und es löst einen Fehler aus. Soll ich die geklonte Datenquelle am Ende wieder an ihren ursprünglichen Platz kopieren? – TheGateKeeper

+0

@TheGateKeeper - Ihre Frage stellt sich heraus, über Referenzen und Referenztypen zu sein, erkennen Sie das. –

+0

@TheGateKeeper am Ende? Nein, du solltest deine Probleme richtig angehen und das "Warum". Wie Henk sagte, sollten Sie mehr Daten über den Fehler neu formulieren und hinzufügen, wo Sie darauf zugreifen, etc. Grundsätzlich müssten Sie synchronisieren - oder erneut aufrufen, wenn an anderen Orten verwendet (wenn möglich, nicht immer so einfach) – NSGaga

Verwandte Themen