Einfrieren der Windows Forms Anwendung verhindern

  • C#

Es gibt 26 Antworten in diesem Thema. Der letzte Beitrag () ist von VB.neter0101.

    Ich möchte meine Problemstellung nun etwas erweitern. Zuvor fasse ich kurz zusammen, was sich bisher hier zusammengetragen hat. Ich habe eine sehr rechenintensive Funktion zur Berechnung der Fibunacci Folge implementiert. Dies geschah bewusst, da ich so das einfrieren einer Windows Forms Anwendung demonstrieren/hervorrufen konnte. Für dieses Problem sollte eine Lösung gefunden werden, diese fand sich dann auch in der Verwendung von await Task.Run(() => ausg = fibu(x));. Mit dieser Lösung konnte ich dann die Form bewegen/verkleinern/vergrößern, während im Hintergrund die rechenintensive Funktion ablief.

    Jetzt möchte ich dieses Problem etwas erweitern. Angenommen meine rechenintensive Funktion greift auf ein Kontrollelement zu, sagen wir mal auf ein DataGrid, dann erscheint resultiert folgende Fehlermeldung "Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement Form1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde". Meine Frage wäre an dieser Stelle: Wie kann man dieses Problem lösen?

    Eine Idee wäre zuerst Daten zu sammeln (in der rechenintensiven Prozedur) und dann die (berechneten) Ergebnisse zurückspielen in das DataGrid. Der @ErfinderDesRades hatte an dieser Stelle Hier etwas ähnliches beschrieben. Aber führt dieses "Aufteilen" nicht zu einer deutlich verlängerten Laufzeit? Daher wie würde man das gut und praktikabel lösen?
    @VB.neter0101 Das Zauberwort heißt Invoke() bzw. BeginInvoke().
    Bevor wir das vertiefen, solltest Du Deine Anforderungen präzisieren:
    Ein Control alle 1000 Iterationen, 20 Controls alle 10 Iterationen oder so.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die Zauberworte hat er doch schon selber gefunden, verlinkt an der Stelle

    VB.neter0101 schrieb:

    Der @ErfinderDesRades hatte an dieser Stelle Hier [...]
    Die Verlängerung der Laufzeit ist eine Frage, die Du Dir selber stellen solltest. Wie lange ist Deine nebenläufige Prozedur unterwegs, bis Du relevante Ergebnisse bekommst? Mir ist klar, dass es bei unendlichen Folgen per Definition kein Ende gibt, aber ... ach, das hat RfG ja selber schon in den Raum geworfen.
    Nuja, wenn Du Performancefragen hast, probier es aus. Vielleicht merkst Du ja selber so am schnellsten, wie oft die Daten angezeigt werden dürfen, bevor es unerträglich langsam wird. Vielleicht ja nie ...
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VB.neter0101 schrieb:

    Jetzt möchte ich dieses Problem etwas erweitern. Angenommen meine rechenintensive Funktion greift auf ein Kontrollelement zu, sagen wir mal auf ein DataGrid, dann erscheint resultiert folgende Fehlermeldung "Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement Form1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde". Meine Frage wäre an dieser Stelle: Wie kann man dieses Problem lösen?
    Weiter lesen im Tut - Stichwort "Update Gui".
    Nämlich im Tut wird das sehr effizient gelöst, indem Gui-Aktualisierungen, die schneller als 300ms erfolgen, unterbunden werden, weil unnütze Performance-Fresser.
    Weil so schnell kann niemand gucken.
    @RodFromGermany pro Iteration befülle ich ein DataGridView mit einer zusätzlichen Zeile. Hintergrund ist folgender: Ich lasse mir die Verzeichnisse meines Systems ausgeben und stelle die in dieser Liste dar. Wenn ich auf die Async Anweisung verzichte, dann friert die Anwendung ein, bis der Prozess dann erfolgreich beendet wurde. Jetzt habe ich daher async eingebaut und ich verwende nun das was ich im Code unten "pseudocode mäßig" hinzugefügt habe. Mein Control wird nun immer geupdatet. Die Frage ist das so gut genug?

    C#-Quellcode

    1. _dataGrid.Invoke(new Action(() => _dataGrid.Rows.Add(...)));

    VB.neter0101 schrieb:

    gut genug
    Je nach dem.
    Wie lange dauert die Berechnung einer Zeile?
    Wenn Du z.B. 10 Zeilen berechnest und dann 10 Zeilen auf ein Mal anhängst, geht das wesentlich schneller, da der Invoke-Overhead auf 10% geschrumpft wird.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!