Während große Dateien verarbeitet werden hängt das ganze Programm

  • VB.NET

Es gibt 9 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Während große Dateien verarbeitet werden hängt das ganze Programm

    Hallo Zusammen,

    ich habe ein Tool programmiert, dass sehr große CSV-Dateien lädt, auswertet und danach berechnungen anstellt.

    Wenn er z.B. gerade eine 300 MB CSV bearbeitet, hängt das ganze Programm. Auch wenn er mit einer Datei fertig ist, die sauber schließt etc.. das Programm reagiert erst, wenn alle Dateien fertig sind und es die nächste Benutzer-Eingabe erwartet.

    Kann mir jemand einen Gedanken-Anstoß geben, wie man das verhindert? Kann man z.B. irgendwie die Arbeit auf die CPU-Kerne verteilen? Also das Programm ansich auf einen anderen Kern wie die Funtkion, die die Dateien bearbeitet?

    Danke und schönen Gruß
    Jan
    Jo, dazu brauchst Du eigene Threads. Schau Dir dazu ThreadPools, Tasks, async-await etc. an. ;)
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Danke :) Manchmal muss man einfach nur wissen, nach welchem Thema man googln muss :)

    Bissl getüffelt und schon klappt es.

    Am Ende hat noch ein "Control.CheckForIllegalCrossThreadCalls = False" im Load Event der Form gefehlt, aber das war auch noch lösbar :)
    Hab den Aufruf zwar noch nicht ganz verstanden, aber muss ja nicht alles kapieren, was ich tippe ^^

    *PS:
    Ich frage mich, warum ich für alle Tools in der Firma immer PHP verwendet hab... vor 1 Woche habe ich mit VB angefangen und das ist sooviel praktischer und macht mehr spaß
    Hi
    Control.CheckForIllegalCrossThreadCalls ist genau der falsche Ansatz. Schau' dir mal BeginInvoke und Invoke des Fensters an. CheckForIllegalCrossThreadCalls ist eigentlich eine "Sicherheitsmaßnahme", damit du dir nicht ins Bein schießt, wenn du aus einem anderen Thread auf die Form zugreifst, weil keine Garantie für Synchronität mehr besteht.
    BeginInvoke hingegen führt eine Operation auf der GUI aus (sobald die entsprechende Nachricht erreicht wird), Invoke wartet sogar noch auf die Fertigstellung der Nachricht. Es wird hierbei ein "Delegat" angegeben.

    Gruß
    ~blaze~
    Jo, ist super, dass Du Dir das selber zusammensuchst, aber ​CheckForIllegalCrossThreadCalls versteckt alles eigentlich nur, anstatt es richtig zu lösen und das ist nat. schlecht. Weil dann kann es sein, dass Fehler etc. mal einfach nicht auftauchen und dann suchst Du Dich tot.

    Einfach (Begin)Invoke aufrufen und schon kannst Du vom Nebenthread aus auf das UI zugreifen.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Heißt das nicht ans Bein pinkeln?? ;)

    Aber zurück zum Thema: Hab invoke jetzt mal in der MS Referenz überflogen, ist mir für heute abend aber zu kompliziert ;) für mein nächstes größeres projekt werde ich das aber angehen :)
    ___
    Edit 5 min später... :)

    äh, achso, ändert sich da nur der Aufruf.. dachte da muss man mehr tun...

    statt

    'teil1= New System.Threading.Thread(AddressOf berechnung)
    'teil1.Start()

    nehm ich dann:

    Invoke(New MethodInvoker(AddressOf berechnung))

    Aber Programm hängt trotzdem! Aber egal :) Bekomm ich morgen hin! Will euch nicht länger nerven ! :)

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Dystopia“ ()

    Dystopia schrieb:

    Invoke(New MethodInvoker(AddressOf berechnung))

    Es hängt weil du nicht verstehst was Invoke macht. Invoke führt den Code wieder auf dem Hauptthread aus. Wenn du jetzt die "berechnung" wieder aufm Hauptthread ausführst, dann bringt dir das rein gar nichts. Sinn und Zweck wäre es sämtliche Zugriffe auf die Form mit Invoke zu machen (z.B. Fortschrittsanzeige aktualisieren, Ergebnis anzeigen,...) und die berechnung selbst ohne Invoke auszuführen.


    Opensource Audio-Bibliothek auf github: KLICK, im Showroom oder auf NuGet.
    Pack mal deinen Thread wieder rein. Dann nimmst du CheckFor... raus (bzs. belässt es auf True). Und dann debuggst du.
    Du wirst einige Exceptions kriegen, halt die UNsicheren Threadübergriffe. Und genau an den Zeilen machst du aus deinem Code ein Invoke mit Delegate.
    »There's no need to "teach" atheism. It's the natural result of education without indoctrination.« — Ricky Gervais
    Gleich als Hinweis, um das von @thefiloe noch genauer zu erläutern:
    Führe die Verarbeitung, Beschaffung, usw. von Daten im Thread aus. Updates der GUI kannst du nach bestimmten Abständen (z.B. 100ms über die System.Diagnostics.StopWatch-Klasse) erledigen. Um diese Updates dann durchzuführen ist es dann notwendig, Invoke bzw. BeginInvoke aufzurufen.
    Der Thread, den du erzeugst, ermöglicht quasi paralleles Verhalten. D.h. du kannst zwei Vorgänge eben parallelisieren, wodurch sie dann scheinbar gleichzeitig ablaufen. Die GUI selbst läuft in einem spezifizierten Thread ((Begin)Invoke führt diese Aufgabe dann auf eben diesem Thread aus), wenn du einen Thread erzeugst, läuft die Methode, die du im Konstruktor des Threads angibst, parallel ab, sobald Thread.Start aufgerufen wird. Wie du dir vorstellen kannst, kann man mit dieser Threading-Geschichte aber wilde Sachen anstellen, wenn nicht gewährleistet wird, dass die Zugriffe garantiert in der richtigen Reihenfolge, bzw. in einer zulässigen Art und Weise durchgeführt werden. Da es an dir ist, diese zu erhalten, musst du entsprechende Dinge erledigen. Die Werkzeuge werden dir bereitgestellt (z.B. SyncLock, die ganzen Sychronisations-Klassen aus System.Threading und ein paar "Tricks", wie z.B. speziell verwendete Variablen, das ist aber erst mal eine andere Geschichte). Die GUI selbst verwendet intern ein eigenes System über Nachrichten. Das wird so organisiert, dass du eine Nachrichten"schlange" hast, d.h. es gehen Nachrichten ein und diese Nachrichten werden nach-und-nach vom GUI-Thread abgearbeitet. Beim BeginInvoke wird bspw. eine Nachricht angehängt und im GUI-Thread werden alle noch zu erledigenden Nachrichten (neuzeichnen, bspw. oder auch Klicks oder Tastatureingaben), bevor das BeginInvoke abgearbeitet wird. Der andere Thread, also der, der BeginInvoke aufgerufen hat, arbeitet derweil weiter. Das ist auch genau der Unterschied zum Invoke: Invoke wartet, bis die Nachricht abgearbeitet wurde. So kann es beim Invoke z.B. nicht passieren, dass die Daten, die du beim Invoke-Aufruf angegeben hast, sich ändern, bis die Nachricht erreicht wird, da der Daten-Thread ja pausiert ist.

    Allgemein kommt's dann auf deine Aufgabe an, wie man vorgeht. Es ist auf jeden Fall sinnvoll, dieses zeitverzögerte Updating vorzunehmen. Viele Dinge in einem Rutsch zu erledigen, beschleunigt auch oftmals Vorgänge.

    Gruß
    ~blaze~

    Dystopia schrieb:

    Invoke
    sollte nur dazu dienen, Daten aus einem Thread an der GUI anzuzeigen. Wenn Du da was falsch machst, wird die komplette Berechnung in den Main-Thread invoked, da hast Du nix gekonnt.
    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!