Eine Aufgabe ist ein object, das verwendet wird, um den Zustand einer aktuell-executing async function darzustellen. Aufgabenobjekte werden verwendet, um festzustellen, wo eine asynchrone Funktion suspended, und die values der local variables an diesem Aussetzungspunkt aufweisen.
Die Aufgaben werden gleichzeitig in einer kooperativen Multitasking-Umgebung ausgeführt.
Eine Aufgabe kann zeitlich begrenzt sein, basierend auf einer lifespan von einer oder mehreren Aktualisierungen, bevor sie abgeschlossen ist.
Die Aufgaben können in beliebiger logischer Reihenfolge aufeinander folgen, sich überschneiden, gestaffelt sein usw.
Der Sequenz- und Überlappungsfluss der Aufgabe wird durch die Verwendung von structured oder unstructured concurrency expressions spezifiziert.
Jede Aufgabe kann gleichzeitig in beliebiger logischer zeitlicher Reihenfolge angeordnet sein, sich überschneiden, gestaffelt sein und so weiter. Intern könnte eine Aufgabe einen caller (oder sogar mehrere Aufrufer) und null oder mehr abhängige Unteraufgaben haben, die ein call graph (im Gegensatz zu einem call stack) bilden.
Eine Aufgabe ähnelt einem thread, hat aber gegenüber Threads den Vorteil, dass die context switching zwischen Aufgaben keine Systemaufrufe, keine aufwendige Speicherung von Kontextzuständen und keine Aufrufe zum Blockieren des Prozessors erfordert und ein Prozessor zu 100% ausgelastet werden kann). Du brauchst keine Synchronisation wie mutexes oder semaphores, um kritische Abschnitte zu schützen, und es ist keine Unterstützung durch das Betriebssystem erforderlich.
Die Klasse task(t:type) ermöglicht die direkte programmatische Abfrage und Bearbeitung von Aufgaben auf unstrukturierte Weise, obwohl es allgemein empfohlen wird, Aufgaben durch strukturierte Gleichzeitigkeitsausdrücke zu bearbeiten, um mehr Klarheit, Leistung und Effizienz zu erzielen.
Derzeit ist die einzige exponierte Funktion für task Await(), die wartet, bis die aktuelle Aufgabe abgeschlossen ist. Diese Funktion verankert eine Aufgabe und fügt einen Caller hinzu, zu dem sie am Aufrufpunkt zurückkehren kann.
spawn{AsyncFunction3()}
# Get task to query / give commands to
# starts and continues independently
Task2 := spawn{Player.MoveTo(Target1)}
Sleep(1.5) # Wait 1.5 Seconds
MyLog.Print("1.5 Seconds into Move_to()")
Task2.Await() # wait until MoveTo() completed
Ähnlich wie im obigen Beispiel werden auch im folgenden Beispiel strukturierte Gleichzeitigkeitsausdrücke verwendet:
sync:
AsyncFunction3() # Task 1
block:
Player.MoveTo(Target1) # Task 2
Sleep(0.5) # Wait 0.5 Seconds
Target1.MoveTo(Target2)
block: # Task 3
Sleep(1.5) # Wait 1.5 Seconds
MyLog.Print("1.5 Seconds into Move_to()")