Laden...

Blockieren trotz Invoke

Erstellt von Thoxx vor 14 Jahren Letzter Beitrag vor 14 Jahren 1.154 Views
Thoxx Themenstarter:in
112 Beiträge seit 2008
vor 14 Jahren
Blockieren trotz Invoke

Ich versuche mich gerade bei WPF an Invokes, da ich das mit WindowsForms schon mal ausprobiert hatte, dachte ich eigentlich, dass ich das bei WPF ähnlich adaptieren kann.
Aber entweder hab ich das Prinzip doch nicht verstanden oder irgendwo anders einen Fehler. Ich hab mir auch schon die FAQ angeschaut und die Suchfunktion bemüht, aber irgendwie steh ich immer noch auf dem Schlauch.

Ich hab eine WPF Application, die zwei Textboxen hat, einen Button und eine Listbox (lbResult).
In den zwei Textboxen steht Start- und Endwert für Primfaktorzerlegung, per Button soll das ganze gestartet werden und die Ergebnisse immer in die Listbox.

Mein Problem ist jetzt, dass bei der Berechnung zwar die Listbox ständig mit den neuen Ergebnissen gefüllt wird und ich das auch sehe, aber dafür alles andere blockiert. Mit der Applikation kann ich keinerlei Interaktion mehr durchführen. Ich sehe nur die ganze Zeit, wie die Listbox befüllt wird.

Ablauf:
Bei Drücken des Buttons wird ein Thread angelegt und dieser gestartet:

Thread t = new Thread(new ThreadStart(delegate() { CalcPrim(from, to, out newArr); }));
t.Start();

CalcPrim wird also aufgerufen:


public void CalcPrim(decimal from, decimal to, out ArrayList PFG)
{
    [...]
    for (decimal x = from; x < to; x++)
    {
        //Berechnung
        [...]
        //wenn aktuelle Berechnung fertig -> Ausgabe in Listbox
        ShowProgress(PFG, x, to);
    }
}

und bei ShowProgress kommt es zu der Ausgabe, wo dann der Fehler liegen dürfte



public delegate void updateListBoxDelegate(string ergebnis);
private void listBoxInsert(string s)
{
    lbResult.Items.Insert(0, s);
}


public void ShowProgress(ArrayList PFG, decimal aktuell, decimal max)
{
    [...]
    string ergebnis;
    [...]

    if (lbResult.Dispatcher.CheckAccess())
    {
         lbResult.Items.Insert(0, ergebnis);
     }
     else
     {
         this.Dispatcher.Invoke(new updateListBoxDelegate(listBoxInsert), ergebnis);
     }
}

Danke schon mal im voraus 🙂

3.430 Beiträge seit 2007
vor 14 Jahren

Hallo,

das Problem ist wohl dass du jedes Ergebnis sofort ausgibst.
Und dadurch hängst du andauernd an der GUI und sagst also -> item hinzufügen -> item hinzufügen...

dadurch belastest du den GUI-Thread wieder so viel dass dieser sich aufhängt.
Du musst also deine ausgaben irgendwie bündeln (d.h. du fügst nur alle 100 Zahlen hinzu (alle zusammen)) oder du suchst dir eine andere Option.

Aber das Problem liegst ziemlich sicher daran dass du jedes zwischenresultat ausgibst, und das blockiert den GUI-Thread.

Das Problem hättest du wohl auch in WinForms

Gruss
Michael

T
16 Beiträge seit 2008
vor 14 Jahren

Hallo,

@michlG: Deine Antwort klingt plausibel. Ich habe das Szenario mal nachgestellt, und das ganze auf 3 Rechnen mal getestet. Komischerweise läuft es auf meinen Vista 32-Bit Rechner so wie man sich das vorstellt, das heißt, während jedes Ergebnis hinzugefügt wird, kann man noch die Form bewegen und Buttons bedienen etc.

Auf einem anderem Rechner "hängt" dagegen die Form fest.

Hat dafür auch jemand eine Erklärung?

3.971 Beiträge seit 2006
vor 14 Jahren

In Vista übernimmt das Zeichen der Forms und Controls die Grafikkarte und nicht die CPU. Je nach dem ob du eine einfache oder gute Grafikkarte besitzt, kommt es zu unterschiedlichen Resultaten. Der Hauptvorteil ist aber, die CPU wird dadurch stark entlastet.

Die so gewonne Prozessorzeit lässt sich aber nur nutzen, wenn man seine Arbeit oder lange Berechnungen asynchron ausführt.

Ein ständiges Invoke wäre allerdings der falsche Weg, selbst ein BeginInvoke bringt nicht optimale Resultate

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

Thoxx Themenstarter:in
112 Beiträge seit 2008
vor 14 Jahren

Hätte irgendwie gedacht, dass das bei so einem Fall dann nur stockt oder Interaktion verzögert ausgeführt werden... daran hab ich irgendwie nicht gedacht 😁
Mit dem Ändern der Ausgabe gehts auf jeden Fall, also nicht jedes ausgeben sondern immer "gebündelt". Danke für den Hinweis 🙂

3.971 Beiträge seit 2006
vor 14 Jahren

Mit dem Ändern der Ausgabe gehts auf jeden Fall, also nicht jedes ausgeben sondern immer "gebündelt"

Oder nur das anzeigen, was der Nutzer auch verarbeiten kann. Am besten mit einem DispatcherTimer sich die aktuellen Werte holen.

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