Eine Funktion mehrfach starten

  • Hallo liebe AutoIter,

    ich brauche eure Unterstützung bei folgendem Vorhaben.

    Ich habe eine Textdatei mit n Einträgen pro Zeile (für das Beispiel sagen wir mal 100 Einträge).

    Diese Einträge möchte ich zählen lassen.

    Dafür nehme ich $n = FileReadToArray($Textdatei)

    Weiterhin definiere ich eine Variable die für die Anzahl der zu startenden Instanzen stehen soll.

    Als Beispiel $i = 10 für 10 zu startende Instanzen

    Jede Instanz soll 10 Einträge aus der Textdatei lesen und zum Weiterverarbeiten nutzen.

    Also $p = Ubound($n) / $i

    Jetzt soll mittels for-Schleife die Funktion aufgerufen werden und wie folgt arbeiten (Beispiel: for $x = 1 to $i):

    _Funktion(1) lese die Einträge aus der Textdatei von 1-10 und verarbeite sie.

    _Funktion(2) lese die Einträge aus der Textdatei von 11-20 und verarbeite sie.

    _Funktion(3) lese die Einträge aus der Textdatei von 21-30 und verarbeite sie usw.

    Ist dies möglich?

    Wenn ja, wie gehe ich vor?

    • Offizieller Beitrag

    Um andere Instanzen mit Inhalt zu versorgen, musst du diese (kompilierte Datei, nicht Funktion) mit Parametern aufrufen.

    Ich würde so vorgehen:

    - Skript 1 (Aufrufskript):

    Liest Textdatei in Array, jede Zeile ein Eintrag. Iteriert durch das Array und fügt Parameterstrings zusammen: "Zeile 1" & "SPACE" & "Zeile 2" & ... - Sind 10 Parameter zusammengefügt wird das Verarbeitungsskript aufgerufen und der Parameterstring mit übergeben. Intern zurücksetzen Parameterstring und weiter durch Array iterieren usw. usf.

    - Skript 2 (Verarbeitungsskript):

    Arbeitet das Parameterarray ($CMDLINE) ab, mit dem von dir vorgesehenen Code.

  • BugFix vielen Dank für deine schnelle Unterstützung

    Folgendes habe ich bis jetzt.

    Als nächstes möchte ich das Verarbeitungsskript erstellen.

    Wie übergebe ich den String richtig, sodass das Verarbeitungsskript diesen Zeile für Zeile verarbeitet?

    • Offizieller Beitrag

    Du teilst die Anzahl der Listeneinträge durch die gewünschte Anzahl an Instanzen. Es ist eher unwahrscheinlich, dass dieses ein ganzzahliger Wert wird. Also musst du dich entscheiden, ob du die nächstgrößere oder -kleinere Ganzzahl verwenden möchtest (Ceiling / Floor). Die Anzahl der möglichen Prozesse brauchst du nicht in einer Schleife abarbeiten - das ergibt sich von selbst. Nehmen wir an du hast das Verarbeitungsskript kompiliert als "work.exe". Parameter-Aufruf wäre dann z.B. so:

    ShellExecute("work.exe", '"param string 1" "param string 2" "param string n"')

    In deinem Aufrufskript gehst du so vor:

    Das Verarbeitungsskript sollte kein Problem sein. Siehe hier.

  • BugFix

    Vielen Dank für das Aufrufskript.

    Ich stehe aber grade irgendwie im Wald.

    Aus dem Aufrufskript werden die Parameter ausgegeben.

    Wie binde ich diese nun korrekt in die kompilierte work.exe ein?

    Im Verarbeitungsskript muss ich diese Paramter ja bekannt geben bzw. mit ihnen in der Funktion arbeiten.

    Leider verstehe ich das nicht so ganz.

  • BugFix

    Habs jetzt durchdrungen und verstanden.

    Aufrufskript:

    Hier musste ich am Ende aber einen Sleep(1000) einbauen.

    Denn sonst kloppen sich die jeweiligen Verarbeitungsprogramme um die Einträge und es kommt zu Fehlern in der Exportdatei.

    Verarbeitungsprogramm:

  • Hi Lashandan

    Ich habe es nur ganz kurz überflogen, nicht getestet :

    1. Statt :

    ShellExecute($sExe, $sString & " " & $start)

    Sleep(1000)

    könnest Du :

    ShellExecuteWait... verwenden.

    2. Func Aufruf() :

    -> Niemals Global Deklarationen in einer Funktion verwenden.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • Hi Musashi

    Ich möchte ja, dass sich mehrere Instanzen gleichzeitig starten und nicht das aufeinander gewartet wird, bis die andere fertig ist.

    Dann hätte ich mit ShellExecuteWait() nichts gekonnt.

    Die globalen Deklarationen habe ich auf local geändert.

    Das hätte mir schon vorher auffallen müssen ^^

    Danke dafür ;)

  • Ich möchte ja, dass sich mehrere Instanzen gleichzeitig starten und nicht das aufeinander gewartet wird, bis die andere fertig ist. Dann hätte ich mit ShellExecuteWait() nichts gekonnt.

    Stimmt, in diesen Fall wäre ShellExecuteWait() ungeeignet.

    Gruß Musashi

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • In dem Fall würde ich wie in Linux mit dem Lockfile-Prinzip arbeiten: Einfach eine Datei erstellen, wenn du die Datei zum bearbeiten öffnest und danach wieder löschen. Vor dem erstellen und beim Scheitern des erstellens (2 erstellen gleichzeitig) => Solange die Datei existiert: warten.

    Bzw.: Wenn du eine Datei zum schreiben öffnest, kann einanderer Prozess die Datei garnicht beschreiben ;)

  • Hallo Lashandan!

    Ich verwende bei meinen Scripts auch Parallelisierung damit Scripte schneller abgearbeitet werden.

    Ich würde dir empfehlen jeden einzelnen PC als eigene Abfrage zu starten und die Ergebnise in eine Tempdatei zu schreiben.

    Wenn alle Abfragen abgeschloßen sind, ließt du die Tempdateien ein und erzeugst eine Gesamtdatei.

    (Damit ersparst du dir die Lockfile Problematik.)

    In der Startdatei gibt es eine Variable die $i_ProcessCount heißt. Dort kann man Angeben wieviele Abfragen gleichzeitig starten sollen. Die Anzahl hängt stark davon ab was man im Verarbeitungsscript alles macht.

    Deine Abfrage ist recht schnell abgearbeitet, somit könnte man die Anzahl stark erhöhen und somit wäre die Abfrage sehr schnell erledigt.

    Ich hatte noch einige Ideen wie man diese "gleichzeitigen" Starts dynamisch regeln könnte, habe diese aber noch nicht in das Script eingebaut.

    Man könnte die Speicherauslastung am System von dem man das Script startet, mit einbeziehen und sobald eine gewisse Speichermenge überschritten wird, wird die Anzahl der ausgeführten Scripte reduziert.

    Das gleiche könnte man auch mit der CPU Auslastung machen. Oder natürlich beides.

    Start Script:

    Spoiler anzeigen

    Verarbeitundsprogramm:

    Spoiler anzeigen

    If not :?: then ?( else :thumbup:

    2 Mal editiert, zuletzt von Concara (6. Mai 2019 um 10:58)

  • Hi,

    zunächst, was sind das denn für Textdateien mit welchen Einträgen, die von vielen "gleichzeitig" (24-Kernprozessor?!) gestarteten Prozessen abgearbeitet werden müssen?

    Wenn ich sehe, dass du mit FileReadToArray($Textdatei) arbeitest, was ohnehin eine der langsamsten Autoitfunktionen ist, dann frage ich mich ernsthaft, ob es nicht Sinn machen würde, dein PROBLEM zu schildern, statt an einer von dir vermuteten (!) "guten" Lösungsmöglichkeit rumzudoktoren!

    Stichwort X-Y-Problem!

    Mit mehreren Prozessen eine Datei zu bearbeiten macht nur dann wirklich Sinn, wenn ausreichend Prozessorkerne mit eigenem (großen) Cache bzw. Speicher zur Verfügung stehen.

    Wenn obige Scripte auf einem bspw. Vierkernprozessor mit angenommen 12 "Threads" (Programmstarts) abgewickelt werden sollen, dann dauert das idR länger, als nur mit 4 Programmstarts. Windows nimmt dem laufenden Thread sowieso über die Zeitscheiben seine Arbeit weg um die anderen Threads zu bedienen. Wenn man das auf die Spitze treibt und 200 "Threads" startet, dann bleibt der Rechner stehen, weil Windows mehr mit der Verwaltung der Threads zu tun hat, als Zeit für das "Problem" zur Verfügung zu stellen!