Laden...

Invoke will nicht (TargetInvocationException)

Erstellt von MOnsDaR vor 15 Jahren Letzter Beitrag vor 15 Jahren 4.211 Views
M
MOnsDaR Themenstarter:in
25 Beiträge seit 2008
vor 15 Jahren
Invoke will nicht (TargetInvocationException)

Moin!

Ich weiß, dass das Thema Invoke schon bis zum Erbrechen durchexerziert wurde und ich habe auch die Suche schon ordentlich bemüht. Leider übersehe ich scheinbar bei jedem Lösungsansatz eine Kleinigkeit oder ich habe ein exotischeres Problem als ich vermute.

Ich habe im Prinzip den Standard- Invoke Fall:

Ein eigenständiger Thread erstellt bei mir in einer Funktion ein Stackpanel und sendet dieses verpackt in einem Event an meine GUI.
Meine GUI fängt dieses Event ab und soll dann das StackPanel einer ListBox hinzufügen.

Inklusive Invoke kommt dann folgender Code zustande:

public partial class Window1
	{ [...]
        private delegate void ItemReceivedDelegate(object sender, ListItemEventArgs e);
        void tracker_ListItemReceived(object sender, ListItemEventArgs e)
        {
            if(ListBoxTracker.Dispatcher.CheckAccess())
            {
                ListBoxTracker.Items.Add(e.Panel);
                ListBoxTracker.Items.Refresh();
            }
            else
            {
                ListBoxTracker.Dispatcher.Invoke(new ItemReceivedDelegate(tracker_ListItemReceived),
                                 sender,
                                 e);
                return;
            }
        } 
[...]
}

Nun bekomme ich jedoch trotz allem eine TargetInvocationException. Mit Invoke habe ich bisher keine Erfahrungen gemacht (zumindest keine tiefergehenden). Kann es sein, dass ich irgendwo in diesem Code eine Kleinigkeit übersehen habe?

Ich hoffe ihr könnt mir weiterhelfen, der Google- Suchmarathon konnte es leider nicht...

Achso:
Ein ähnliches Thema ist schon einmal unbeantwortet geblieben (LINK)

Vielen Dank für die Bemühungen schonmal im Voraus,
MOnsDaR

Meine Projekte:
ClipboardReader
MusicMasher (auf Eis gelegt)
PAMTracker 4.02

1.665 Beiträge seit 2006
vor 15 Jahren

Ein eigenständiger Thread erstellt bei mir in einer Funktion ein Stackpanel und sendet dieses verpackt in einem Event an meine GUI.

Fehler 1: Erstellen von Controls außerhalb des UI Threads.

Meine GUI fängt dieses Event ab und soll dann das StackPanel einer ListBox hinzufügen.

Fehler 2: Zugriff eines Controls auf ein Control aus einem anderen Thread.

Definier ein Event á la CreateStackPanel.

In der UI, wo du das event abonnierst, machst du ein <Control>.Invoke(<Methode>).
In dieser Methode machst du deine UI Zugriffe. Dort erstellst du also dein StackPanel.

M
MOnsDaR Themenstarter:in
25 Beiträge seit 2008
vor 15 Jahren

Alles klar, werde im Laufe des Wochenendes mein Design umbauen (Thread übergibt Daten im Event, Daten werden per Databinding dann an die ListBoxItems gebindet) und mich wahrscheinlich Sonntag dann melden inwieweit das Ganze läuft.

Danke für die Antwort, hab mir schon gedacht, dasses nicht die tollste Lösung ist, die Stackpanel im Thread anzulegen. Dachte allerdings nicht, dass es solche Probleme hervorrufen wird.

Meine Projekte:
ClipboardReader
MusicMasher (auf Eis gelegt)
PAMTracker 4.02

M
MOnsDaR Themenstarter:in
25 Beiträge seit 2008
vor 15 Jahren

Sooo, wurd leider etwas später als Sonntag.
Das Ganze funktioniert nun einwandfrei. Eingehende Daten werden in ein Stackpanel gepackt welches widerrum in die Listbox geadded wird.

Allerdings hat sich direkt das nächste Problem aufgetan:
Ich möchte bei jedem eingehenden Item gern die ListBox ToBottom scrollen. Hierfür kann man ja die ScrollView aus der ListBox "extrahieren" und muss deren Methode "ToBottom()" aufrufen.
Dies löst leider eine InvocationException aus und ich kann trotz aller Versuche dieses nicht verhindern.

private delegate void ItemReceivedDelegate(List<MessageContent> givenContent);
void tracker_ListItemReceived(object sender, ListItemEventArgs e)
{
      Dispatcher.Invoke(DispatcherPriority.Normal,
      (ItemReceivedDelegate)delegate(List<MessageContent> givenContent)
      {
            [..hier wird ein StackPanel gebaut..]
            AddNewListItem(newStackPanel);
      }, e.Content);
}


private void AddNewListItem(StackPanel givenStackPanel)
{
     ListBoxTracker.Items.Add(givenStackPanel);

     //Scroll down listbox
     ScrollViewer sv = VisualTreeHelper.GetChild(ListBoxTracker, 0) as ScrollViewer;
     sv.ScrollToBottom();
}

Ich hoffe ich habe nur das unwichtige gekürzt und der Codeteil ist leicht verständlich.

  • Wenn ich den Teil mit der Scrollbar entferne, geht es perfekt (also keine Invoc.Exception von ListBoxTracker
  • Wenn ich den ScrollViewer- Teil reinnehme, o.g. Exception

Müsste der Code nicht komplett im Kontext der GUI ausgeführt werden? Warum wird bei der ListBox keine Exception geschmissen?
Wenn ich die Scrollview nochmal mit einem Dispatcher/Delegat-Konstrukt umschließe wie in der oberen Funktion kommt auch die TargetInvocationException

Mir schwirrt der Kopf, ich hoffe jemand kann mir helfen...

Danke,
MOnsDaR

Meine Projekte:
ClipboardReader
MusicMasher (auf Eis gelegt)
PAMTracker 4.02

3.971 Beiträge seit 2006
vor 15 Jahren

Was ist e.Content für ein Typ?

Funktioniert vllt.


internal delegate void Foo();
void tracker_ListItemReceived(object sender, ListItemEventArgs e) {
  Dispatcher.Invoke(new Foo(delegate() {
    //e.Content ist hier auch verfügbar, auch ohne Angabe von Argumenten.
    AddNewListItem(newStackPanel);
  }));
}

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

M
MOnsDaR Themenstarter:in
25 Beiträge seit 2008
vor 15 Jahren

e.Content beinhaltet die Daten, die ins Stackpanel geschrieben werden sollen (vereinfacht kann man sagen eine Liste mit Strings)

Das mit dem Delegaten werd ich nachher zuhause mal anpassen. Aber das wird keine Auswirkungen auf das Scrollviewer- Problem haben denke ich?!

Meine Projekte:
ClipboardReader
MusicMasher (auf Eis gelegt)
PAMTracker 4.02

M
MOnsDaR Themenstarter:in
25 Beiträge seit 2008
vor 15 Jahren

Sooo, auch dieses Problem ist gelöst 😃

Anstatt dem o.g. Konstrukt habe ich die Funktion

ListBoxTracker.ScrollIntoView(anyObject);

genutzt.
Diese scrollt zum angegebenen Objekt. Wenn ich also nach dem hinzufügen eines neuen Objektes direkt diese Funktion mit dem Objekt aufrufe, wird immer ans Ende gescrollt.

Manchmal ist die Lösung doch weitaus näher als man annimmt 😃

Das Projekt geht in großen Schritten voran und wird sicherlich demnächst im Projekte- Bereich von mir vorgestellt werden.

@eichhoernchen: Danke für den Tipp mit den Delegaten, mein Code ist nun weitaus übersichtlicher.

Meine Projekte:
ClipboardReader
MusicMasher (auf Eis gelegt)
PAMTracker 4.02