Laden...

ObservableCollection<T> Änderungen aus anderem Thread

Erstellt von Spook vor 10 Jahren Letzter Beitrag vor 10 Jahren 1.224 Views
S
Spook Themenstarter:in
248 Beiträge seit 2008
vor 10 Jahren
ObservableCollection<T> Änderungen aus anderem Thread

Hallo zusammen,

ich habe ein Problem mit einer ListBox im Zusammenspiel mit einer ObservableCollection<T>.
Grob zusammengefasst passiert folgendes:

Ich habe eine ObservableCollection<T> welcher zuvor einer ListBox (ItemsSource Property) zugewiesen wurde. Zu einem späteren Zeitpunkt wird das Objekt, in welchem die Collection liegt, zerstört. Dabei wird die Collection wieder aus der ListBox entfernt (im GUI Thread).
Danach rufe ich Clear() auf der Collection auf, was zu einer Exception in der ListBox führt, weil der Aufruf aus dem Nicht-GUI Thread kommt.

Hier ein Beispeilcode:

        private void addButton_Click(object sender, RoutedEventArgs e)
        {
            ObservableCollection<string> collection = new ObservableCollection<string>();
            collection.Add("a");
            collection.Add("b");
            collection.Add("c");
            listBox.ItemsSource = collection;
        }

        private void removeButton_Click(object sender, RoutedEventArgs e)
        {
            Thread thread = new Thread(ThreadProc);
            thread.IsBackground = true;
            thread.Start();
        }

        private void ThreadProc()
        {
            ObservableCollection<string> collection = null;

            Action removeItems = () =>
            {
                collection = listBox.ItemsSource as ObservableCollection<string>;
                listBox.ItemsSource = null;
            };

            if (!listBox.Dispatcher.CheckAccess())
            {
                listBox.Dispatcher.Invoke(removeItems);
            }
            else
            {
                removeItems();
            }

            if (collection != null)
            {
                collection.Clear(); // <- Exception
            }
        }

Das Problem ist, dass nach dem Setzten von "listbox.ItemSource = null;" die Listbox immernoch an dem CollectionChanged Event angemeldet ist.
Warum hängt sich die ListBox nicht wieder von dem Event ab? Passiert dies erst zu einem späteren Zeitpunkt?
Wie kann ich sicherstellen, dass alles richtig aufgeräumt ist, bevor ich den GUI Thread wieder verlasse?

582 Beiträge seit 2008
vor 10 Jahren

Hallo, das ist ein übliches Verhalten. Du hast nur vollen zugriff auf deine Objekte in dem Thread, in dem sie erstellt werden. Da deine Collection in einem anderen Thread erstellt wurde funktioniert dein Aufruf nicht.

Warum das so ist, wird hier beschrieben.

Link

Gruß dat Tala

S
Spook Themenstarter:in
248 Beiträge seit 2008
vor 10 Jahren

Hallo Taladan,

ich habe mir die Seite angesehen. Das Beispiel passt jedoch nur bedingt zu meinem Problem.
Wie völlig richtig dargestellt wird, muss man bei allen Änderungen an den Daten aus einem anderen Thread auf die 'Umlenkung' in den GUI Thread achten. Das passiert bei mir auch, funktioniert auch ohne Probleme.
Es geht bei mir darum, dass ich die Bindung der Collection an die Listbox trenne, diese sich jedoch nicht von dem CollectionChanged-Event dieser abhängt, oder zumindest nicht sofort. Da ich mit Dispatcher.Invoke(...) arbeite, wird dies auch sicher abgearbeitet, bevor im nicht-GUI Thread Clear() aufgerufen wird.
Ich gehe einfach davon aus, dass wenn ich ItemsSource auf null setzte, dass dann die Bindung gelöst wird, und nicht, für mich nicht feststellbar, irgendwann später.