Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

Stelle Fragen zur Programmierung mit Autohotkey

Moderator: jNizM

User avatar
bichlepa
Posts: 183
Joined: 15 Aug 2014, 06:44
Location: Germany
Contact:

Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

29 Feb 2016, 11:44

Ich arbeite weiterhin an AutoHotFlow und kämpfe mit den GUIs.
Ich habe alle GUIs in Funktionen gepackt, weil es praktisch ist. Es gibt die Schwierigkeit, dass der Benutzer durch mehrere GUIs hintereinander geleitet wird. (z.B. Wenn der Benutzer eine neue Verbindung erstellt und auf einen leeren Ort zieht, wird ein neues Element erstellt. Es wird dann zuerst gefragt, welcher Verbindungstyp es sein soll, dann muss der Benutzer den Typ des neu zu erstellenden Elements auswählen, dann den Untertyp des Elements auswählen und dann die Parameter des Elements anpassen. Wenn der Benutzer bei einem der Fenster abbricht, muss die erstellte Verbindung und evlt. das erstellte Element wieder gelöscht werden.)
In der zurzeit veröffentlichten Version von AutoHotFlow wird die Funktion, welche ein GUI zeigt, aufgerufen und zeigt den GUI und geht sofort auf ein Return zu. Wenn der Benutzer das Fenster schließt (z.B. durch auf OK drücken), wird noch in der GUI-Funktion entschieden, was weiter ausgeführt wird (nächsten GUI öffnen, oder, bei Abbrechen, die gerade erstellten Elemente löschen). Das ist aber sehr schwer zu handhaben, denn je nach dem, was der Benutzer gemacht hat, muss die Abfolge der GUIs anders sein und im Falle des Abbrechens, müssen entweder gar keine oder verschiedene Elemente gelöscht werden.
Jetzt habe ich es dahingehend geändert, dass in der Routine, welche die Benutzereingaben verarbeitet, die Funktionen mit den GUIs öffnet und auf das Ergebnis wartet, um dann flexibel weiter entscheiden zu können. In der GUI Funktion muss aber eine Endlosschleife durchlaufen werden, welche ständig prüft, ob der Benutzer das Fenster geschlossen hat. Das ist wesentliche einfacher zu implementieren, aber hat den Nachteil, dass wenn durch die Benutzereingabe ein Thread unterbrochen wurde, dieser erst wieder läuft, wenn sich der Benutzer durch alle Fenster geklickt hat. Es gibt auch weitere Probleme dieser Art aufgrund von unterbrochenen Threads.

Lange Rede, kurzer Sinn. Ich möchte im folgenden Beispiel bis zum Kommentar ;Keep everything until here bleibt und sich das Programm im großen gleich verhält. Ich will aber nicht, dass die Arbeitsroutine dauerhaft unterbrochen werden kann, wenn die GUIs geöffnet werden. Ist das irgendwie möglich. Ich habe schon mit Thread Prioritäten experimentiert, bin aber auf nichts brauchbares gekommen.

Code: Select all

SetTimer, doaroutine,200
return 

f12::

ret:=opengui1()
if ret=OK
{
	MsgBox pressed OK
	;make further actions
	ret:=opengui2()
	if ret=OK
	{
		MsgBox pressed OK
		;make further actions

	}
	else if ret=cancel
	{
		MsgBox pressed cancel
		;make other further actions
	}
}
else if ret=cancel
{
	MsgBox pressed cancel
	;make other further actions
}

return
;Keep everything until here

openGUI1()
{
	static resultGUI1
	resultGUI1:=""
	gui,1:add,button,g1ChosenOK w100,OK
	gui,1:add,button,g1ChosenCancel w100 X+10 yp,Cancel
	gui,1:show,, GUI 1
	Loop
	{
		if resultGUI1
			break
	}
	return resultGUI1
	
	1chosenOK:
	gui,1:destroy
	resultGUI1:="OK"
	return
	1chosenCancel:
	gui,1:destroy
	resultGUI1:="Cancel"
	return
	1guiclose:
	ExitApp
}
openGUI2()
{
	static resultGUI2
	resultGUI2:=""
	gui,2:add,button,g2ChosenOK w100,OK
	gui,2:add,button,g2ChosenCancel w100 X+10 yp,Cancel
	gui,2:show,, GUI 2
	Loop
	{
		if resultGUI2
			break
	}
	return resultGUI2
	
	2chosenOK:
	gui,2:destroy
	resultGUI2:="OK"
	return
	2chosenCancel:
	gui,2:destroy
	resultGUI2:="Cancel"
	return
	2guiclose:
	ExitApp
}

doaroutine()
{
	ToolTip Working
	sleep 150
	ToolTip Not Working
}
Scripting is too complicated? Try AutoHotFlow, the graphical automation tool! Written in AutoHotkey.
just me
Posts: 9425
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

29 Feb 2016, 17:30

Moin,

wenn die Funktion doaroutine() Deine Arbeitsroutine darstellen soll, kannst Du mal mit Critical experimentieren. Außerdem ist dringend zu empfehlen, in Deine GUI Warteschleifen ein Sleep einzubauen, oder sie durch ein WinWaitClose zu ersetzen.
User avatar
bichlepa
Posts: 183
Joined: 15 Aug 2014, 06:44
Location: Germany
Contact:

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

01 Mar 2016, 01:30

Das sleep habe ich in diesem Beispiel vergessen, in AutoHotFlow ist es drin.
Critical habe ich auch schon erwägt. Das Problem ist, dass manche "Arbeitsroutinen" (z.b. Ausführung des Flows) unter Umständen mehrere Sekunden dauern. Gleichzeitig soll aber die Bedienung des Hauptfensters möglich sein. Und gleichzeitig muss innerhalb von Millisekunden auf Befehle vom Manager reagiert werden. Und gleichzeitig muss, wenn der Flow aktiv ist, auf diverse andere Ereignisse (z. B. Hotkey) reagiert werden, um die nächste Ausführung des Flows zu beginnen.
Was optimal wäre, ist, wenn ich sagen könnte, statt einem sleep für 100 ms, führe die wartenden Threads 100 ms lang aus und kehre dann zurück. Echtes Multithreading wäre auch eine Lösung, aber ich wurde aus den bisher gefundenen Forum Posts darüber nicht schlau.
Ich hoffe, ich stoße mit meinen Anforderungen nicht auf die Grenze der Möglichkeiten von AHK.
Scripting is too complicated? Try AutoHotFlow, the graphical automation tool! Written in AutoHotkey.
just me
Posts: 9425
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

01 Mar 2016, 02:05

Moin,
Ich hoffe, ich stoße mit meinen Anforderungen nicht auf die Grenze der Möglichkeiten von AHK.
Ich weiß es nicht, aber irgendwann sind die Grenzen erreicht, wenn man quasi gleichzeitig viele gleichberechtigte Routinen in dem einen AHK-Thread ausführen will. Zum Thema Multi-Threading könnte sich ein Blick auf AHK_H lohnen, das mehrere Threads unterstützen soll. Ich habe das noch nicht probiert, HotKeyIt ist aber normalerweise sehr hilfsbereit, wenn man AHK_H spezifische Probleme hat.

Generell würde ich meinen, dass Dein erster Ansatz mit den schnellen Returns für solch eine Umgebung der bessere ist. Ich weiß aber selbst, dass die Ablaufsteuerung in solchen Fällen recht kompliziert werden kann. Bei Fenstern für Benutzereingaben kann man vor überraschenden Benutzeraktionen schützen, indem man sie 'modal' macht, d.h. die anderen Fenster zeitweise 'disabled' und ggf, auch unerwünschte Hotkeys deaktiviert. Aber das blockt natürlich auch Teile der Anwendung.

Das ist Alles recht theoretisch. Ich würde auch gern versuchen, Dir praktisch zu helfen, bräuchte dafür aber ein konkretes Problem in Deinem Echtskript.

Grüße,
just me
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

01 Mar 2016, 05:18

Moin,

Nur eine Idee:
Du könntest u.U. auch eine Art Nachrichtenversandt einrichten: die Guis senden Nachrichten. Die Nachrichten landen auf einem Stack. Der Stack wird von der Routine z.B, mit einem Timer abgearbeitet.
ciao
toralf
User avatar
bichlepa
Posts: 183
Joined: 15 Aug 2014, 06:44
Location: Germany
Contact:

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

02 Mar 2016, 12:05

Danke, just me.
Ich habe mal AHK_H heruntergeladen, allerdings wird es, wie es aussieht, seit 2013 nicht mehr weiterentwickelt. Wenn ich meinen "Editor.ahk" versuche, auszuführen, bekomme ich einen Syntax-Fehler.
Ich habe soeben das Projekt geforkt, es würde mich sehr freuen, wenn du mir praktisch helfen würdest. :thumbup: Die für das bereits beschriebene Problem relevanten Dateien sind im Ordner "Editor\User Interface" und heißen "ui_mouse.ahk" (Verarbeitung von Benutzereingaben im Hauptfenster) und "ui_Element_Settings" (alle Fenster mit den Einstellungen für die Elemente).
https://github.com/bichlepa/AutoHotFlow ... otFlow-1.0

@toralf
Danke für die Idee, aber ich glaube, in diesem Fall wird es mindestens genauso kompliziert, wie der ursprüngliche Ansatz mit sofortigem Return.
Scripting is too complicated? Try AutoHotFlow, the graphical automation tool! Written in AutoHotkey.
just me
Posts: 9425
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

02 Mar 2016, 16:25

Hallo bichlepa,

da bist Du irgendwie falsch gelandet. Das geht mir allerdings auch immer wieder so. HotKeyIt pflegt AHK_H nach wie vor und hält es auf dem Stand der aktuellen AHK Version. Schicke ihm einfach mal eine PM.

Ansonsten werde ich mal schauen, ob mir etwas einfällt.
just me
Posts: 9425
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

03 Mar 2016, 05:26

Moin bichlepa,

genau so hatte ich es schon befürchtet. Zig-tausende 'lines of code' verteilt auf ziemlich viele einzelne Skripte. Das ist schon der richtige Ansatz, macht es aber für Nichteingeweihte sehr kompliziert, dem Ablauf zu folgen.
Ich kann hier nicht einmal den Editor starten, weil ich die default Aktion für .ahk Dateien auf Edit gesetzt habe. Die Run Anweisungen landen deshalb direkt in PSPad, meinem AHK-Editor.

Ich würde Dir gern helfen, nachdem Du das korrigiert hast, brauche dann aber dafür Deine Hilfe. Ich kann mich nur Schritt für Schritt herantasten. Daher wäre es gut, wenn Du mir eine spezielle Problemsituation schildern könntest, zusammen mit dem Weg, wie ich über die Oberfläche dahin gelange, und den beteiligten Skripten. Ich sehe leider keine andere Möglichkeit, ohne mich für eine wirklich lange Zeit mit dem Quellcode zu beschäftigen.

Bis dann!
just me
User avatar
bichlepa
Posts: 183
Joined: 15 Aug 2014, 06:44
Location: Germany
Contact:

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

03 Mar 2016, 11:46

Hi just me.
Entschuldige mich für den unübersichtlichen Code. :oops: Ich habe noch sehr wenig Erfahrungen mit so großen Projekten. Sag mir, was ich noch besser machen muss, damit es für dich angenehmer wird. Das Problem mit der Default Aktion sollte jetzt gelöst sein.

Das Problem wird anschaulich sichtbar, wenn du folgendes machst:
Öffne den Manager (AutoHotFlow.ahk) und öffne den Flow "test" in der Kategorie "Test", in dem du auf "Bearbeiten" klickst. Es ist zurzeit der einzige funktionsfähige Flow, weil ich bisher nur die Aktionen "Neue Variable" und "Traytip" angepasst habe. Du kannst den Flow ausführen, wenn du oben auf "Starten" klickst. Die Aktionen werden sichtbar durchlaufen und die Traytips sollten erscheinen. (Die Ausführgeschwindigkeit ist noch sehr langsam, was ich noch angehen werde). Wenn das klappt, versuche, während der Ausführung, ein Element zu bearbeiten (z.B. Doppelklick auf eine Verbindung oder eine Aktion) oder, während ein Element markiert ist, eine neue Verbindung zu ziehen. Da haben wir das Problem: die Ausführung wird (meistens) stoppen, bis du fertig bist und die Element-Einstellungs-Fenster schließt. ("Mestens", weil die Ausführung unter Zuhilfenahme von Timers in mehreren Durchläufen geschieht, mit 10 ms Pause dazwischen)
Der relevante Code befindet sich, wie bereits erwähnt in den beiden Dateien "ui_mouse.ahk" und "ui_Element_Settings.ahk". In "ui_mouse.ahk" wird die Benutzereingabe verarbeitet. Dort wird entschieden, ob, welche und in welcher Reihenfolge die Einstellungsfenster geöffnet werden, die als Funktionen in der Datei "ui_Element_Settings.ahk" vorhanden sind. Es gibt insgesamt vier verschiedene Fenster, die geöffnet werden können: ElementSettings.open(), selectSubType(), selectConnectionType(), selectContainerType(). Darin befindet sich, nach dem Erstellen des Fensters, dieser oder ähnlicher Code, welcher darauf wartet, dass der Benutzer das Fenster schließt und dann die Variable "NowResultEditingElement" zurückgibt. Beim Schließen des Fensters wird die Variable "NowResultEditingElement" beschrieben. Das führt aber dazu, dass angehaltene Threads nicht weitergehen und dadurch z.B. die Ausführung im Hintergrund angehalten wird.

Code: Select all

if (wait=1 or wait="wait")
{
	Loop
	{
		if (NowResultEditingElement="")
			sleep 100
		else 
		{
			if (NowResultEditingElement!="aborted")
				setElement.ConnectionType:=NowResultEditingElement
			break
		}
	}
}
return NowResultEditingElement
Scripting is too complicated? Try AutoHotFlow, the graphical automation tool! Written in AutoHotkey.
User avatar
bichlepa
Posts: 183
Joined: 15 Aug 2014, 06:44
Location: Germany
Contact:

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

03 Mar 2016, 15:48

Danke, HotKeyIt!
Multi-Threading wäre wirklich eine Lösung für einige Probleme. Ich habe eine neue Frage zu den Threads gepostet. Ich würde gerne zuerst das Rendern des Hauptbildschirms angehen, was auch gelegentlich "hängen bleibt" und viel Performance frisst. Wenn das in einem eigenen Thread gemacht würde, wäre es ein großer Gewinn.
Scripting is too complicated? Try AutoHotFlow, the graphical automation tool! Written in AutoHotkey.
just me
Posts: 9425
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

04 Mar 2016, 05:28

Moin bichlepa,

ich meinte nicht, dass Dein Code 'unübersichtlich' im Sinne von 'schlecht' ist. Auch die Aufteilung auf mehrere Skripte ist richtig. Bei mehreren 1000 Zeilen hättest wohl sonst selbst Du einige Probleme damit. Es ist nur recht schwierig für Seiteneinsteiger, sich schnell darin zurechtzufinden.

Ich werde die korrigierte Version mal testen, kann das aber erst in der kommenden Woche. Sollten sich bis dahin alle Probleme durch AHK_H erledigt haben, sag das bitte hier.

Bis dann!
just me
User avatar
bichlepa
Posts: 183
Joined: 15 Aug 2014, 06:44
Location: Germany
Contact:

Re: Auf GUI Ergebnis warten, ohne andere Threads zu blockieren

10 Mar 2016, 14:47

@ just me
Nach langer Fehlersuche schein es jetzt mit Multithreading zu funktionieren :)
Ich habe jetzt konkrete Vorstellungen, wie ich weiter vorgehen werde und die oben beschriebenen Probleme werden sich damit voraussichtlich lösen lassen.
Scripting is too complicated? Try AutoHotFlow, the graphical automation tool! Written in AutoHotkey.

Return to “Ich brauche Hilfe”

Who is online

Users browsing this forum: No registered users and 30 guests