Mehrere Funktionen paralell ablaufen lassen?

  • Ich habe ein Programm programmiert bei dem ich mit einem Button mehrere Funktionen aufrufe.

    Beispielsweise:


    Das mal als Beispiel angenommen. Ich möchte das nun alle Funktionen gleichzeitig ablaufen. Zurzeit ist es aber so, das die Funktionen nacheinander ablaufen. Also erst wenn der 1. Loop vorbei is,t beginnt die zweite Funktion und nach der zweiten erst die Dritte.

    Ich möchte das alle Funktionen paralell arbeiten.

  • Hab gerae nochmal ein wenig geforscht

    Was sagt ihr zu dieser Variante?


    [autoit]


    #include <ButtonConstants.au3>
    #include <GUIConstantsEx.au3>
    #include <WindowsConstants.au3>
    $counter1 = 0
    $counter2 = 0
    $counter3 = 0

    [/autoit][autoit][/autoit][autoit]

    Opt("GUIOnEventMode", 1)
    GuiCreate("Test",450,400)
    $Zeit_1 = GuiCtrlCreateLabel("0",10,5,100,20)
    $Zeit_2 = GuiCtrlCreateLabel("0",10,35,100,20)
    $Zeit_3 = GuiCtrlCreateLabel("0",10,65,100,20)
    $Button1 = GUICtrlCreateButton("Start", 152, 48, 153, 49)
    GUICtrlSetOnEvent(-1, "Button1Click")
    $Button2 = GUICtrlCreateButton("Stop", 152, 104, 153, 49)
    GUICtrlSetOnEvent(-1, "Button2Click")
    GUISetOnEvent($GUI_EVENT_CLOSE, "Form1Close")
    GUISetState(@SW_SHOW)

    [/autoit][autoit][/autoit][autoit]

    do
    $msg = GuiGetMsg()
    until $msg = -3

    [/autoit][autoit][/autoit][autoit]

    Func Form1Close()
    exit
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func Button1Click()
    AdlibRegister("_counter1",100) ; 10tel Sek
    AdlibRegister("_counter2",500) ; 1/2 Sek
    AdlibRegister("_counter3",1000) ; Sek
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    Func Button2Click()
    AdlibUnRegister("_counter1")
    AdlibUnRegister("_counter2")
    AdlibUnRegister("_counter3")
    EndFunc

    [/autoit][autoit][/autoit][autoit]

    func _counter1()
    $counter1= $counter1+ 1
    GuictrlSetData($Zeit_1,$counter1)
    endfunc

    [/autoit][autoit][/autoit][autoit]

    func _counter2()
    $counter2= $counter2+ 1
    GuictrlSetData($Zeit_2,$counter2)
    endfunc

    [/autoit][autoit][/autoit][autoit]

    func _counter3()
    $counter3 = $counter3 + 1
    GuictrlSetData($Zeit_3,$counter3)
    endfunc

    [/autoit]


    Aber sobald ich in irgendner Funktion ein Sleep oder nen Loop habe dann ists schon wieder vorbei... Naja schade

    Es müsste echt noch einen DoEvents Befehl geben. Damit wäre das Problem gelöst.

    4 Mal editiert, zuletzt von KloMeister (20. Dezember 2011 um 03:34)

  • Moin, ich bin mir nicht sicher was genau ihr unter "DoEvents" versteht, eventuell gibt es sowas in Autoit aber habe nie zuvor den Begriff DoEvents gehoert, somit kann ich ihn mit keinem Befehl aus Autoit in Verbindung setzen :P

    Gruß Marvin

    • Offizieller Beitrag

    Moin, ich bin mir nicht sicher was genau ihr unter "DoEvents" versteht, eventuell gibt es sowas in Autoit aber habe nie zuvor den Begriff DoEvents gehoert, somit kann ich ihn mit keinem Befehl aus Autoit in Verbindung setzen :P

    Gruß Marvin


    Ganz grob erklärt:
    Das ist eine VB-Funktion, die bei Aufruf das Ausführen der Funktion nicht mehr durch die VB-Umgebung kontrolliert, sondern diese einfach dem Betriebssystem zum Fraß vorwirft und sagt: Mach mal. :D
    Somit kann sich VB dann um andre Dinge "kümmern", wie etwa einem anderen Funktionsaufruf.

  • Hallo,

    DoEvents würde dir in deinem Fall nicht helfen, da dein Skript durch das Sleep bzw. die Schleife keine weiteren Funktionen abarbeiten kann, da es nicht parallel arbeitet.
    In VB gibt es die Funktion DoEvents, um dem BS kurzzeitig die Kontrolle zu übergeben um andere Funktionen abzuarbeiten, die nichts mit dem VB-Programm zu tun haben.
    Das ist unter Umständen dann notwendig, wenn sich das VB-Programm z.B. in einer sehr großen Schleife oder Berechnung mit einer Progressbar beschäftigen würde, dann könnte dem BS durch DoEvents z.B. Zeit gegeben werden, den Bildschirm neu zu Zeichnen.

  • Unter Visual Basic 6 konnte ich z.B eine "Delay" Funktion erstellen, bei der paralell ablaufende Funktionen trotzdem weiter arbeiten:


    Achtung nicht wundern das ist VB6 Code

    Und als Beispiel dann aufrufen für 1 Sek Pause:

    Code
    Delay 1000

    Das schöne war eben, das alle anderen gerade auch ablaufenden Funktionen, ebenso weiterarbeiten obwohl eine Delay Funktion in einer anderen gerade ablaufenden Funktion eingebaut war.

  • Hi,
    zeig doch mal den entsprechende VB6-Code. Das was du machen möchtest, wäre dann Multithreading, und das ist auch unter VB6 nicht so ohne Weiteres möglich.

  • Naja ich möchte nichts spezielles machen und habe auch keinen entsprechenden VB Code.

    Ich war mit AutoIT am programmieren und wollte eben etwas programmieren was nicht geklappt hat.
    War mehr oder weniger eh nur eine rumspielerei vondaher nicht so wichtig.


    Bei VB6 nehm ich dann meist mehrere Timer der die Sachen abfragt oder soetwas in der Richtung um dort das Problem zu lösen.
    Ein Timer ist ja auch mehr oder weniger ne Schleife, aber paralell läuft alles andere weiter.


    Bei AutoIT habe ich leider keine Möglichkeit gefunden, wie ich das nun mache und deswegen wollt ich hier mal nachfragen.
    Eine richtige Lösung habe ich leider bislang immer noch nicht.

  • Das oben genannte Beispiel würde übrigens so mit Visual Basic 6 klappen:


    [autoit]

    Private Sub Command1_Click()
    Call loop1
    Call loop2
    Call loop3
    End Sub

    [/autoit][autoit][/autoit][autoit]

    Private Sub loop1()
    Do Until Text1 = "Test"
    DoEvents
    Loop
    MsgBox "Text1 hat die Bezeichnung Test"
    End Sub

    [/autoit][autoit][/autoit][autoit]

    Private Sub loop2()
    Do Until Text2 = "Test"
    DoEvents
    Loop
    MsgBox "Text2 hat die Bezeichnung Test"
    End Sub

    [/autoit][autoit][/autoit][autoit]

    Private Sub loop3()
    Do Until Text3 = "Test"
    DoEvents
    Loop
    MsgBox "Text3 hat die Bezeichnung Test"
    End Sub

    [/autoit]


    Dank der DoEvents Funktion friert nichts ein und alle Funktionen laufen dann paralell ab.
    In VB6 ist das halt mit 1 Befehl sehr leicht gelöst. Schade das das in AutoIT nicht geht.


    Man kann das sicher auch anders programmieren, so das man diese Funktion nicht benötigt.

    Ich bin es halt gewohnt mit dieser Funktion zu arbeiten, da ich früher mit VB6 programmiert habe. Habe die Funktion da öfters verwendet was sich als recht praktisch herausgestellt hat.

    2 Mal editiert, zuletzt von KloMeister (20. Dezember 2011 um 14:49)

  • Du musst mit der Programmiersprache auch den Programmierstil etwas ändern. Wie wäre es denn so?

    [autoit]


    Func OKButton()
    $cond1=False,$cond2=False,$cond3=False
    Do
    Sleep(50)
    Select
    Case blablabla = "blablabla" and not $cond1
    msgbox(0,"","Ereignis 1 erfüllt")
    $cond1=True
    Case blablabla = "blablabla" and not $cond2
    msgbox(0,"","Ereignis 2 erfüllt")
    $cond2=True
    Case blablabla = "blablabla" and not $cond3
    msgbox(0,"","Ereignis 2 erfüllt")
    $cond3=True
    EndSelect
    Until $cond1 and $cond2 and $cond2
    EndFunc

    [/autoit]

    Twitter: @L3viathan2142
    Benutze AutoIt persönlich nicht mehr, da ich keinen Windows-Rechner mehr besitze.

  • Hier hab ich auch noch eine Möglichkeit herausgefunden:

    So kann man mit Hilfe einer Timerschleife und einer selbst festgelegten Zeit des Timers, eine Variable auf einen Wert prüfen, ohne das andere Funktionen dabei gestoppt werden, wie es z.B bei einem Loop der Fall wäre

    Ist aber wohl indirekt das selbe wie AdlibRegister? oder gibt es da einen Unterschied?


    [autoit]

    Global $Label, $i = 0
    Global $Label2, $i2 = 0
    $hForm = GUICreate('Test', 400, 400)
    $Label = GUICtrlCreateLabel('', 20, 20, 100, 16)
    $Label2 = GUICtrlCreateLabel('', 20, 40, 100, 16)
    GUISetState()
    $hDll = DllCallbackRegister('_Timer', 'none', '')
    DllCall('user32.dll', 'int', 'SetTimer', 'hwnd', 0, 'int', 0, 'int', 250, 'ptr', DllCallbackGetPtr($hDll))
    $hDll = DllCallbackRegister('_Timer2', 'none', '')
    DllCall('user32.dll', 'int', 'SetTimer', 'hwnd', 0, 'int', 0, 'int', 500, 'ptr', DllCallbackGetPtr($hDll))

    [/autoit][autoit][/autoit][autoit]

    Do
    Until GUIGetMsg() = -3
    Func _Timer()
    $i += 1
    GUICtrlSetData($Label, $i)
    if $i = 10 then MsgBox(1,"","Timer1 Zahl ist 10")

    [/autoit][autoit][/autoit][autoit]

    EndFunc ;==>_
    Func _Timer2()
    $i2 += 1
    GUICtrlSetData($Label2, $i2)
    if $i2 = 10 then MsgBox(1,"","Timer2 Zahl ist 10")
    EndFunc ;==>_

    [/autoit]

    Einmal editiert, zuletzt von KloMeister (21. Dezember 2011 um 02:47)

  • Würde mal sagen ist das selbe wie Adlib und pausiert ebenso wie Adlib das Script wärend die Funktion ausgeführt wird.

    Andy hat mir ein Schnitzel gebacken aber da war ein Raupi drauf und bevor Oscar das Bugfixen konnte kam Alina und gab mir ein AspirinJunkie.

    • Offizieller Beitrag

    Die Timer-UDF ist nicht dasselbe wie AdlibRegister.
    Hier mal an einem Beispiel veranschaulicht:

    Spoiler anzeigen
    [autoit]


    #include <Timers.au3>
    Global $iCount = 0
    $hGui = GUICreate('Test')
    $hLabel = GUICtrlCreateLabel($iCount, 10, 10, 40, 20)
    GUISetState()
    AdlibRegister('_Counter')
    MsgBox(0, 'Test1', 'Counter angehalten, wegen MsgBox')
    AdlibUnRegister('_Counter')

    [/autoit] [autoit][/autoit] [autoit]

    $iTimer = _Timer_SetTimer($hGui, 250, '_TimerCounter')
    MsgBox(0, 'Test2', 'Counter trotz MsgBox nicht angehalten')
    Do
    Until GUIGetMsg() = -3
    _Timer_KillAllTimers($hGui)
    Exit

    [/autoit] [autoit][/autoit] [autoit]

    Func _Counter()
    $iCount += 1
    GUICtrlSetData($hLabel, $iCount)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _TimerCounter($hWnd, $Msg, $iIDTimer, $dwTime)
    #forceref $hWnd, $Msg, $iIDTimer, $dwTime
    $iCount += 1
    GUICtrlSetData($hLabel, $iCount)
    EndFunc

    [/autoit]