Hallo zusammen,
ich hoffe ihr könnt mir ein weiteres Mal helfen, ich komme einfach nicht weiter, aber konnte mein Problem soweit eingrenzen.
Das Ganze ist leider nicht so einfach erklärt und für Code Beispiele ist alles etwas zu umfangreich geworden, aber ich versuche mein bestes!
Mein AutoIT Script ist mittlerweile recht umfangreich geworden und ich nutze jetzt schon seit sehr langen Forking mithilfe von AuThread (https://github.com/jesobreira/authread - mittlerweile aber fast komplett umgeschrieben und erweitert).
Das nutze ich um zb. per Button parallel mehrere API/JSON Abfragen auszuführen und auszuwerten, ohne jeweils auf mein Hauptprogramm warten zu müssen.
Funktioniert auch sehr schön und habe mittlerweile teilweise 5-8 parallele Instanzen am laufen.
Leider zieht das ganz schön an der Performance und es kamen immer mehr und mehr hinzu.
Mein AutoIT Script wird von einem Netzwerklaufwerk ausgeführt, was letztendlich dazu führt das jedes Mal, wenn parallele Abfragen gestartet werden, die Exe sich selbst von dem Netzwerklaufwerk mehrmals startet.
Jetzt bin ich an einem Punkt angelangt wo es dadurch zu langsam läuft und wollte was dagegen tun.
ZitatAlles anzeigenLösung 1:
Ich kopiere das Programm beim ersten Aufruf selbst in den lokalen Temp Ordner von Windows und starte die Threads darüber.
--- leider ging das nie... ich hatte es geschafft die Exe zu kopieren und auch aufzurufen (mir wurde von der Run() Funktion eine PID übergeben), aber kurz darauf beendeten sich die Exe'n von selbst wieder
Lösung 2:
Wegen Zugriffsrechten etc. dachte ich, man könnte das Script nicht aus dem Tmp Ordner starten, daher habe ich eine verkleinerte Exe, die nur die für das Threadding enthaltene Funktionen beinhaltet erstellt und versucht die aus dem gleichen Verzeichnis, wie die Haupt-Exe zu starten.
--- auch hier wieder das gleiche Problem aus Lösung 1. Die Exe'n starten, ich bekomme die PID und beenden sich wieder
Lösung 3:
Mittlerweile habe ich erfahren das man die *.au3 auch direkt aus seiner compilierten AutoIT Exe starten kann... derzeit compiliere ich eine verkleinerte Version als *.a3x und starte diese (anstatt einer 2mb großen Exe, starte ich jetzt eine 80kb große *.a3x pro Thread)
--- ABER AUCH HIER... es startet, ich bekomme die PID und es beendet sich...
Ihr müsst wissen, die obigen Lösungen habe ich in einem größeren Zeitraum versucht und bin nie dahinter gekommen was egt genau falsch läuft.
Mittlerweile habe ich ein besseres Logging für meine Anwendung... wo ich vorher nur die Consolen Ausgabe des MainThreads per Scite erhalten konnte, schreiben meine SubThreads ihre Logs in eine temporäre Log Datei.
Darüber konnte ich weiter eingrenzen was egt beim Threadding passiert, oder eher nicht passiert.
Die Kommunikation der einzelnen Threads geschieht wie im Original über "eine" Ini Datei.
Funktioniert bisher super und gab keine Probleme, wenn "mehrere" Instanzen der gleichen Exe auf diese Zugreifen wollen.
Wenn ich jetzt aber ein SubThread versucht auf diese Ini zuzugreifen, welche zb. meine *.a3x (oder wahrscheinlich auch aus Lösung 1 und 2 probierten >Exe'n), wird die Ini nie gelesen und nach 1-2 Sekunden beendet sich das Script von selbst (ohne Fehler, oder dergleichen).
Hier ein Ausschnitt aus dem Teil, wo die Nachrichten gelesen werden - diese werden im SubThread in einer Endlosschleife ständig abgefragt bis eine Antwort kommt:
Func _AuThread_GetMessage()
;Es wird nach Nachrichten gesucht
_ConsoleLog("_AuThread_GetMessage() - Lese Nachrichten..." & @CRLF)
Local $aArray = IniReadSection($__AuThread_sTmpFile, "msg")
;Prüft ob es einen Fehler gab
If Not @error Then
_ConsoleLog("_AuThread_GetMessage() - Nachrichten erhalten... versuche auszuwerten." & @CRLF)
_ConsoleArray($aArray)
;Geht alle Keys, bzw alle Nachrichten durch >> Key: $aArray[$i][0] (enthält PIDs) - Value: $aArray[$i][1] (enthält die Nachricht)
For $i = 1 To $aArray[0][0]
;Splittet den Key, $aKeySplit[1] ("Empfänger-PID|Sender-PID") beinhaltet die PID des Empfängers und $aKeySplit[2] beinhaltet die PID des Senders
$aKeySplit = StringSplit($aArray[$i][0], "|")
;Prüft nur weiter, wenn der Key über zwei PIDs verfügt (bzw das Array mehr wie einen Eintrag enthält) und somit eine Emfpangs- und Sende-PID existiert
If $aKeySplit[0] > 1 Then
;Prüft ob die linke PID der Nachricht überhaupt die eigene PID des Prozesses ist, weil sonst, ist die an einen anderen Thread gedacht
If $aKeySplit[1] = @AutoItPID Then
;Liest Nachricht
Local $sMsg = IniRead($__AuThread_sTmpFile, "msg", $aArray[$i][0], False)
If $sMsg = False Then Return False
$sMsg = $aKeySplit[2]&"|"&$sMsg ;Fügt an die Nachricht die Sender-PID zur späteren Zuordnung
IniDelete($__AuThread_sTmpFile, "msg", $aArray[$i][0]) ;Löscht die Nachricht
Return $sMsg ;Gibt die Nachricht zurück
EndIf
EndIf
Next
Else
_ConsoleLog("_AuThread_GetMessage() - Konnte keine Nachrichten lesen - ERROR: " & @error & @CRLF)
EndIf
;War nichts erfolgreich, gibts ein False
Return False
EndFunc
Alles anzeigen
"_ConsoleLog()" schreibt die typische Consolen Ausgabe und loggt diese in einer temporären Datei.
Zum weiteren Eingrenzen hatte ich an mehreren Stellen die Ausgaben geloggt und zu prüfen an welche Stelle meine Subthreads kommen und an welche nicht.
Die Zeile "Local $aArray = IniReadSection($__AuThread_sTmpFile, "msg")" erzeugt bei den SubThreads immer ein @ERROR Flag.
Daraus schließe ich, dass die SubThreads keinen Zugriff auf die Ini Datei erhalten.
Hier mein Log eines SubThreads:
2018-09-17 11:58:57 : 14708 - _AuThread_Startup() - gestartet... prüfe, ob es sich um ein Main-, oder SubThread handelt.
2018-09-17 11:58:57 : 14708 - _AuThread_Startup() - Alle Parameter: /AutoIt3ExecuteScript "D:\Stuff\Programmieren\AutoIT\Codes\AutoFan\AutoFan\AutoFan_v2_Threads.a3x" "--au-thread" "_EndSZbyLocation_Ping_Thread"
2018-09-17 11:58:57 : 14708 - _AuThread_Startup() - Es handelt sich um ein SubThread.
2018-09-17 11:58:57 : 14708 - _AuThread_Startup() - Starte Funktion: _EndSZbyLocation_Ping_Thread
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - gestartet
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Prüfe Nachrichten.
2018-09-17 11:58:57 : 14708 - _AuThread_GetMessage() - Lese Nachrichten...
2018-09-17 11:58:57 : 14708 - _AuThread_GetMessage() - Konnte keine Nachrichten lesen - ERROR: 1
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Nachricht von MainThread: False
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Sleep
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Prüfe Nachrichten.
2018-09-17 11:58:57 : 14708 - _AuThread_GetMessage() - Lese Nachrichten...
2018-09-17 11:58:57 : 14708 - _AuThread_GetMessage() - Konnte keine Nachrichten lesen - ERROR: 1
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Nachricht von MainThread: False
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Sleep
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Prüfe Nachrichten.
2018-09-17 11:58:57 : 14708 - _AuThread_GetMessage() - Lese Nachrichten...
2018-09-17 11:58:57 : 14708 - _AuThread_GetMessage() - Konnte keine Nachrichten lesen - ERROR: 1
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Nachricht von MainThread: False
2018-09-17 11:58:57 : 14708 - _EndSZbyLocation_Ping_Thread() - Sleep
Alles anzeigen
Wie ihr seht, startet die Endlosschleife immer wieder die "_AuThread_GetMessage()", welche versucht die Ini zu lesen, aber nicht schafft.
Nochmal zur Verdeutlichung... wenn ich das Threadding mit mehreren Instanzen der "selben" Exe starte, können alle parallel auf diese Ini zugreifen.
Im Regelfall wird die Schleife hier auch nur "einmal" aufgerufen zum Abfragen der Nachrichten.
Ich hoffe ihr konntet mir soweit folgen.
Meine eigentliche Frage... könnt ihr mir sagen was genau falsch läuft?
Können die SubThreads, die quasi anderen Exen, oder eine *.a3x Datei ist nicht drauf zugreifen, weil die MainThread Exe diese blockiert?
Wieso können dann SubThreads, die aus der gleichen Exe entstanden sind darauf zugreifen?
Habt ihr eine Idee wie ich dieses Problem lösen, oder umgehen könnte?
Vielen Dank schon mal fürs durchlesen und für die Hilfe.
Grüße
borsTiHD