Altes Thema Multitasking

  • Hallo, ok ich weiß das multitasking, bzw multithriting nicht ganz einfach ist, deswegen hoffe ich, ihr könnt mir Helfen eine andere Lösung zu finden, bzw habt Ideen für mein Problem.

    ich möchte eine schleife laufen lassen, die in besimmten abständen eine von mir per Hand Aktualisierte Datei an meinen Server schickt.
    gleichzeitig möche ich aber eine überwachung meines USB-Ports, da soll er meine arbeits-fortschrits-Dateien Automatisch darauf speichern wenn dieser eingesteckt wird.
    Beide anwendungen funktionieren ,unabhänging von einander(d.h. in 2 Skripten) einwandfrei
    nun mein problem, ich möchte sie in einem Skript, bzw später .exe vereinen
    Wie bekomm ich beide anwendungen zusammen ohne das eine von beiden Pausiert?
    habe viele Theorien gehört mit Adliebregister, UDF's und TimerInit, aber nichts hat mich zu meinem Erfolg gebracht.

    [autoit]

    ;upload der Datei auf den Server
    #RequireAdmin
    #include <FTPEx.au3>
    #include <Array.au3>
    #include <misc.au3>

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

    While 1
    Sleep (3600000);jede stunde die Datei zum Server schicken
    Global $sPassword = "********"
    Global $sUser = "***************"
    Global $sServer = "***************"
    Global $spath = "@Desktopdir & "arbeitsprojekt.doc"
    Global $sOrdner = "/www"
    Global $sFilename = "arbeitsprojekt.doc"

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

    $hProgress = GUICtrlCreateProgress(8, 32, 297, 25)
    $hLabel = GUICtrlCreateLabel("", 91, 70, 200, 25)
    $hOpen = _FTP_Open("Autoit")
    $hConnect = _FTP_Connect($hOpen, $sServer, $sUser, $sPassword, 1)

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

    _FTP_ProgressUpload($hConnect, $sPath, $sOrdner&$sFilename, "_Update_Progress")

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

    _FTP_Close($hOpen)
    _FTP_Close($hConnect)
    Sleep(1000)
    WEnd
    Func _Update_Progress($iProzent)
    GUICtrlSetData($hProgress, $iProzent)
    GUICtrlSetData($hLabel, "Hochladen bei " & $iProzent & "% (Abbruch mit F8)")
    If _IsPressed("77") Then Return 0
    Return 1
    EndFunc
    ;=========================================================
    ;======================Das 2te Skript=====================
    ;=========================================================
    ;Usbüberwachung und datei schreiben wärend der oberen Schleife
    #RequireAdmin
    Global $strComputer = "."
    Global $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")

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

    $colEvents = $objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceOperationEvent Within 5 Where " _
    & "TargetInstance isa 'Win32_LogicalDisk'")

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

    While 1
    $objEvent = $colEvents.NextEvent
    If $objEvent.TargetInstance.DriveType = 2 Then
    Select
    Case $objEvent.Path_.Class()="__InstanceCreationEvent"
    filecopy(@Desktop & "arbeitshilfe.jpg", $objEvent.TargetInstance.DeviceId,1)
    Case $objEvent.Path_.Class()="__InstanceDeletionEvent"
    msgbox(0,"abgeschlossen","USB-Stick wurde entfernt")
    ExitLoop
    EndSelect
    EndIf
    WEnd

    [/autoit]

    Einmal editiert, zuletzt von AsiX-5 (24. Februar 2011 um 13:09)

    • Offizieller Beitrag

    Ich würde mal sagen, mache beide Scripte erst mal lauffähig.
    Im 1. Teil hast du keine GUI erstellt und auch einen Fehler vor @DesktopDir. Da ist ein " zuviel.
    Die Globalen Variablen werden nur 1 mal erstellt und nicht immer neu bei jedem Aufruf der While Wend Schleife.
    Wenn du beide Scripte lauffähig hast, dann kannst du dir Gedanken machen, wie diese zusammengeführt werden.
    Im Augenblick ist es nur ein unsortierter Codehaufen.

    Zitat

    habe viele Theorien gehört mit Adliebregister, UDF's und TimerInit, aber nichts hat mich zu meinem Erfolg gebracht.


    Alleine dein Sleep(360000) in der 1. Hauptschleife verhindert einen Einsatz von Adlib oder Timern.
    Bei Sleep macht dein Script gar nichts.

  • Alleine dein Sleep(360000) in der 1. Hauptschleife verhindert einen Einsatz von Adlib oder Timern.
    Bei Sleep macht dein Script gar nichts.


    Sleep ist doch das Beste was dir für Adlib passieren kann.
    So hat die CPU ja gerade Zeit die Funktionen zwischendurch auszuführen:

    Adlib-Beispiel
    [autoit]

    AdlibRegister("Test", 1000)

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

    Sleep(10000)

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

    AdlibUnRegister("Test")

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

    Func Test()
    Static $i = 0
    $i += 1
    ConsoleWrite("Test " & $i & @CRLF)
    EndFunc

    [/autoit]


    Da die Begrifflichkeiten meistens nicht ganz klar sind hier nochmal ne kurze Erklärung zu den Unterschieden:

    • Multitasking: Mehrere Programme werden auf einem Prozessor sequentiell abwechselnd ausgeführt so dass eine reale Gleichzeitigkeit nicht existert, aber simuliert werden kann. In AutoIt mit Adlib* umsetzbar.
    • Multithreading: Ein Prozess startet Unterprogramme welche innerhalb eines Shared-Memory Systems verteilt werden können. Z.B. einen anderen CPU-Kern. Threads haben direkten Zugriff auf den Speicher der anderen Threads. In AutoIt nicht umsetzbar. Dafür müsste der Interpreter von Grundauf neu programmiert und erweitert werden um z.B. Race-Conditions vermeiden zu können.
    • MultiProcessing: Mehrere Prozesse werden gestartet welche auf verschiedenen CPU gleichzeitig ausgeführt werden können. Um eine Aufgabe gemeinsam parallel abzuarbeiten bedarf es einer Kommunikation zum Datenaustausch zwischen den Prozessen da die Prozesse in der Regel keinen direkten Zugriff auf den Speicher der anderen Prozesse haben (distributed Memory).
      In AutoIt prinzipiell machbar. Dafür bedarf es aber eines umfangreichen Kommunikationsstandards ( wie z.B. MPI ) für AutoIt welcher meines Wissens nach nicht existiert und in AutoIt auch nicht sonderlich effektiv wäre. Die Programmierung wird auch deutlich schwieriger. Wer schonmal mit MPI programmiert hat wird wissen wovon ich rede. Theoretisch also möglich in der Realität aber sinnlos.

    2 Mal editiert, zuletzt von AspirinJunkie (22. Februar 2011 um 10:31)

    • Offizieller Beitrag

    AspirinJunkie, hast ja Recht. Bin noch nicht richtig wach. 8|

    AsiX-5, dein 2. Scriptteil kann so auch noch nie gelaufen sein, ein @Desktop Macro gibt es nicht und
    beim darauffolgenden & "arbeitshilfe.jpg" fehlt ein \ vor dem Dateinamen .
    Dein ExitLoop verhindert auch ein neueres Ausführen der While Wend Schleife, wenn 1 mal der Stick
    gezogen wird, beeendet sich das Script.
    Bringe beide Teilscripte eigenständig zum laufen, dann basteln wird dir das schon zusammen.

  • so also Die beiden sind es nun :P (im Anhang)
    soweit überarbeitet, bei mir laufen sie, wie gesagt, getrennt voneinander gut, quasi so wie sie sollen, nur susammen bekomme ich sie nicht.
    und wenn ich mich an Adlib versuche bekomme ich Promt:

    AdlibEnable ("_Test", 2000)
    ^ ERROR

    Mir anscheinend zu hoch -.-

    PS: das mit dem Stick rausziehen und beenden hab ich erstmal so gelassen, weil es, wenn es alleine läuft Funktioniert!

  • [autoit]

    AdlibRegister

    [/autoit]

    heißt die Funktion inzwischen, weil mehrere registriert werden können.


    Ja Das weiß ich, nur komme ich leider nicht mit der zurecht. und "Ja" ich habe auch die Google-Funktion und die Hilfe zu Rate gezogen.
    nur weiß ich leider nicht, wie ich Die Adlibregister in meinen beiden Fällen zum Einsatz bringen kann

    • Offizieller Beitrag

    Wunderbar deine 1. Script. 8|
    Du benutzt ein GUICtrlCreateProgress und ein GUICtrlCreateLabel ohne GUI.
    Erstelle erst mal eine GUI bevor du Controls verwenden willst.

    [autoit]

    Global $spath = "C:/" & "arbeitsprojekt.doc"

    [/autoit]

    ist auch falsch.
    Seit wann werden unter Windows die Trenner mit / gechrieben? Probier es mal mit \ :!:
    Die Variablendeklaration muß vor die While Wend Schleife, hab ich dir aber oben schon mal geschrieben.
    Mach erst mal dein Script lauffähig.... :thumbup:

    Edit:

    [autoit]

    Global $sOrdner = "/www"

    [/autoit]


    sollte wohl eher

    [autoit]

    Global $sOrdner = "/www/"

    [/autoit]


    heißen weil $sOrdner&$sFilename sonst /wwwarbeitsprojekt.doc ergibt. :!:

    • Offizieller Beitrag
    Zitat

    so habe es jetzt so. also muss sagen, bei mir funktioniert es(jetzt) ok hattet recht. hatt wwwabrbeitsmappe.doc ausgegeben :-S
    auch mit fehlerhafter GUICtrlCreateProgress und ein GUICtrlCreateLabel was "Raupi" schrieb

    Meiner Meinung nach bist du lernresistent oder du weißt nicht, was du überhaupt in deinem Script machst.
    Für was wird ein Progress und Label erstellt, wenn es nicht verwendet wird, weil es keine darzugehörige GUI gibt?
    Ein Stupfsinniges C&P der Beispieldateien bringt dir nichts. Wenn dir jemand ein fertiges Script vor die Nase knallt,
    ist der Lerneffekt auch gegen Null und wir sind kein scripte mir mal eben Forum.

  • "Meiner Meinung nach bist du lernresistent oder du weißt nicht, was du überhaupt in deinem Script machst"
    Musst ja nicht gleich Ausfällig werden.
    Ja das Script habe ich nicht ganz alleine gemacht, Stimmt aber mir gehts ja auch nicht um Die GUI's, wil ja auch garnichts Vorgekaut bekommen, sondern einfach nur Wege, wie ich diese zusammen bekomme.

    [autoit]

    #RequireAdmin
    #include <FTPEx.au3>
    #include <Array.au3>
    #include <misc.au3>

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

    Global $sPassword = "***"
    Global $sUser = "***"
    Global $sServer = "***"
    Global $spath = "C:\arbeitsprojekt.doc"
    Global $sOrdner = "/"
    Global $sFilename = "arbeitsprojekt.doc"

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

    While 1
    Sleep (60000)
    $hOpen = _FTP_Open("Autoit")
    $hConnect = _FTP_Connect($hOpen, $sServer, $sUser, $sPassword, 1)
    _FTP_ProgressUpload($hConnect, $sPath, $sOrdner&$sFilename, "_Update_Progress")
    _FTP_Close($hOpen)
    _FTP_Close($hConnect)
    Sleep(1000)
    WEnd

    [/autoit]
    • Offizieller Beitrag
    Zitat

    Musst ja nicht gleich Ausfällig werden.

    Naja, wo ich ausfällig geworden bin, weiß ich ja nicht, aber wenn du meinst.

    Zitat

    Meiner Meinung nach bist du lernresistent oder du weißt nicht, was du überhaupt in deinem Script machst.


    Das hat nichts mit Ausfällig zu tun sondern ist eine Feststellung, aufgrund deiner Ignoranz gegenüber meinen Vorposts.

  • Also ich hab mich jetzt an Adlibe Probiert an einem Anderen Beispiel. Wollte den Splash Text blinken lassen, wärend er er (beim einstecken) die Datei auf den Stick schiebt. ich weiß die WHile schleife in AdlibRegister verhindert das weiterkommen. aber bekomm es einfach nicht hin -.-

    [autoit]

    Global $strComputer = "."
    Global $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")

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

    $colEvents = $objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceOperationEvent Within 5 Where " _
    & "TargetInstance isa 'Win32_LogicalDisk'")
    AdlibRegister("Test", 1000)
    while 1
    SplashTextOn("Mappe", "Test ob Adlibe Funktioniert")
    Sleep(2000)
    SplashOff()
    sleep(1000)
    AdlibUnRegister("Test")
    WEnd
    Exit

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

    Func Test()
    EndFunc

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

    while 1
    $objEvent = $colEvents.NextEvent
    If $objEvent.TargetInstance.DriveType = 2 Then
    Select
    Case $objEvent.Path_.Class()="__InstanceCreationEvent"
    if Not FileExists($objEvent.TargetInstance.DeviceId &"\arbeitsmappe.doc") then FileCopy (@WindowsDir&"\arbeitsmappe.doc",$objEvent.TargetInstance.DeviceId &"\arbeitsmappe.doc",1)
    Case $objEvent.Path_.Class()="__InstanceDeletionEvent"
    Exit
    EndSelect
    EndIf
    WEnd

    [/autoit]
  • Ich denke es bringt hier nicht viel dir ein fertiges Skript vorzusetzen.
    Daher hier mal eine Hilfe zur Selbsthilfe:

    AdlibRegister trägt eine Funktion ein welche aller einer gewissen Zeitspanne ausgeführt werden soll.
    In deinem Fall ist das die Funktion mit dem Namen "Test".
    Nun was führt deine Funktion denn aus?
    Kurz und knapp: Nichts, da zwischen "Func" und "EndFunc" ja auch kein ausführbarer Code steht.
    Halten wir also fest: Aller 1s wird bei dir "Nichts" ausgeführt.
    Aber das auch nur 3x, denn nach 3s wird die Funktion wieder deregistriert da nach 2 Sleeps (a 2s und 1s) bei dir schon ein AdlibUnregister folgt (und das wiederholt sogar unendlich mal so viel da es in einer Endlosschleife ohne Abbruchkriterium steht).
    Ab diesem Aufruf (also nach rund 3s) wird "Nichts" nicht mehr jede Sekunde aufgerufen.
    Der Codeteil der unteren While-Schleife wird zudem nie erreicht da er im sequentiellen Code nach einem Exit kommt (was ja das Programm killt bevor es dahinter liegende Codeteile erreicht) und auch nicht in einer Funktion vorkommt.

  • Hallo AsiX-5,

    herzlich willkommen im Forum und viel Spass mit AutoIt.

    Hier kannst du dir die deutsche Hilfe herunterladen.
    Hier gibt es ein AutoIt-Tutorial: http://wiki.autoit.de/wiki/index.php/TutorialSehr hilfreich ist auch das Buch von peethebee

    und jetzt zu deinem Skript: Habe dein Skript mal konsequent gekürzt ohne etwas von der derzeitigen Funktionalität einzubüssen:

    [autoit]

    SplashTextOn("Mappe", "Test ob Adlibe Funktioniert")
    Sleep(2000)
    SplashOff()
    Sleep(1000)

    [/autoit]

    Du solltest die Hilfe durcharbeiten, damit du wenigstens die Grundlagen verstehst, danach kannst du auch über "Pseudo-Multithreading" nachdenken und versuchen es in den Skript zu implementiieren,

    mfg autoBert

  • Danke Dir.
    Ok soweit habe ich versucht Die AdlibRegister-Funktion zu verstehen und hoffe, es ist mir einigermaßen gelungen ;)
    Nur jetzt habe ich Das Problem das er wartet bis der Stick eingesteckt ist und dann zeitgleich Die Splashnachricht blinken lässt und die Datei auf den Stick kopiert.
    Ich wollte aber das diese blinkt, bevor, wärend und nach dem einstecken des sticks aber das hab ich bis hier her noch nicht geschafft. hab schon versuch die Funktionen zu drehen und das "AdlibRegister" anders zu Positionieren. Ist bestimmt igendetwas, was ich nicht richtig bedacht habe! 8|

    [autoit]

    Global $strComputer = "."
    Global $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")

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

    $colEvents = $objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceOperationEvent Within 5 Where " _
    & "TargetInstance isa 'Win32_LogicalDisk'")
    $objEvent = $colEvents.NextEvent

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

    AdlibRegister("_CheckUDPRecv", 200)

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

    Func _CheckUDPRecv()
    If $objEvent.TargetInstance.DriveType = 2 Then
    Select
    Case $objEvent.Path_.Class()="__InstanceCreationEvent"
    if Not FileExists($objEvent.TargetInstance.DeviceId &"\arbeitsmappe.doc") then FileCopy (@WindowsDir&"\arbeitsmappe.doc",$objEvent.TargetInstance.DeviceId &"\arbeitsmappe.doc",1)
    Case $objEvent.Path_.Class()="__InstanceDeletionEvent"
    EndSelect
    EndIf
    EndFunc
    While 1
    SplashTextOn("Mappe", "Test ob Adlibe Funktioniert")
    Sleep(1000)
    SplashOff()
    sleep(1000)
    WEnd

    [/autoit]
    • Offizieller Beitrag

    Scheinbar hat die Strikte Verweigerung, dir ein lauffähiges Beispiel zu geben, dich doch zum lesen motiviert.
    Also schein nicht ganz Hopfen und Malz bei dir verloren zu sein. ;)

    Zu deinem Script:

    [autoit]

    $objEvent = $colEvents.NextEvent()

    [/autoit]


    muß eigentlich in die AdlibFunktion mit aufgenommen werden, weil dort ja das zu Iterierende Event abgefragt wird.
    Bringen wird dir das aber leider gar nichts, weil die Methode wie du die Stickabrage gestaltest für ein AdlibFunktion falsch ist.

    [autoit]

    $colEvents.NextEvent

    [/autoit]

    wartet so lange, bis ein Event auftritt. Das Heißt die AdlibFunktion wird erst
    verlassen wenn auch wirklick ein Stick angesteckt oder gezogen wird. Da du die Adlibfunktion aber alle 200 ms versuchst aufzurufen,
    befindet sich dein Script in einer Endlosschleife. Die While Wend Schleife wird niemals erreicht, und der darin enthaltene
    Code auch nie ausgeführt.

    Damit du es verstehst hab ich dein Script mal angepaßt.
    Schau dir mal die Consolenausgabe an. ;)

    Spoiler anzeigen
    [autoit]

    Global $strComputer = "."
    Global $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")

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

    $colEvents = $objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceOperationEvent Within 5 Where " _
    & "TargetInstance isa 'Win32_LogicalDisk'")
    ;~ $objEvent = $colEvents.NextEvent

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

    AdlibRegister("_CheckUDPRecv", 200)

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

    Func _CheckUDPRecv()
    ConsoleWrite("Timer wird aufgerufen" & @CRLF)
    $objEvent = $colEvents.NextEvent()
    ConsoleWrite("Ein Event wurde ausgelöst !!" & @CRLF)
    If $objEvent.TargetInstance.DriveType = 2 Then
    Select
    Case $objEvent.Path_.Class() = "__InstanceCreationEvent"
    ConsoleWrite("Stick angeschlossen" & @CRLF)
    If Not FileExists($objEvent.TargetInstance.DeviceId & "\arbeitsmappe.doc") Then FileCopy(@WindowsDir & "\arbeitsmappe.doc", $objEvent.TargetInstance.DeviceId & "\arbeitsmappe.doc", 1)
    Case $objEvent.Path_.Class() = "__InstanceDeletionEvent"
    ConsoleWrite("Stick wurde entfernt" & @CRLF)
    EndSelect
    EndIf
    EndFunc ;==>_CheckUDPRecv
    While 1
    SplashTextOn("Mappe", "Test ob Adlibe Funktioniert")
    Sleep(1000)
    SplashOff()
    Sleep(1000)
    WEnd

    [/autoit]

    Aber nicht verzagen, ich habe im Englischen Forum mal was rausgekramt und für dich angepaßt.
    Wenn du also deinen FTP senden Teil als AdlibFunktion laufen läßt, sollte dein Vorhaben klappen.
    Das schlimmste was dir passieren kann ist, das dein FileCopy erst nach dem FTP-Teil ausgeführt wird.
    Mir scheint es aber eher unwahrscheinlich, das du einen Stickwechsel genau während dem FTP-Upload machst.

    Spoiler anzeigen
    [autoit]

    Global $strComputer = "."
    Global $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")
    $sink = ObjCreate("WbemScripting.SWbemSink")
    ObjEvent($sink, "SINK_")
    $colEvents = $objWMIService.ExecNotificationQueryAsync($sink, _
    "Select * From __InstanceOperationEvent Within 5 Where " _
    & "TargetInstance isa 'Win32_LogicalDisk'")

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

    AdlibRegister("Ftpgedoens",10000)

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

    SplashTextOn("Test", "Stick entfernen oder anstecken ! "&@CrLf&"Beachte die Consolenaufgabe.")

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

    While 1
    sleep(50)
    WEnd
    SplashOff()
    Func Ftpgedoens()
    ConsoleWrite("Simulieren des FTP-Teils"& @CRLF)
    for $i= 1 to 15
    Tooltip("Hier läuft was "& $i,100,100)
    Sleep(300)
    Next
    ToolTip("")
    EndFunc
    Func SINK_OnObjectReady($objObject, $objAsyncContext)
    If $objObject.TargetInstance.DriveType = 2 Then
    Select
    Case $objObject.Path_.Class() = "__InstanceCreationEvent"
    ConsoleWrite("Stick angeschlossen, Laufwerk: " &$objObject.TargetInstance.DeviceId & @CRLF)
    If Not FileExists($objObject .TargetInstance.DeviceId & "\arbeitsmappe.doc") Then FileCopy(@WindowsDir & "\arbeitsmappe.doc", $objObject .TargetInstance.DeviceId & "\arbeitsmappe.doc", 1)
    Case $objObject.Path_.Class() = "__InstanceDeletionEvent"
    ConsoleWrite("Sticke " & $objObject.TargetInstance.DeviceId & "wurde entfernt." & @CR)
    EndSelect
    EndIf

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

    EndFunc ;==>SINK_OnObjectReady

    [/autoit]

    Edit: Der verwendete Code ist von Wolf9228 aus dem Englischen Forum.

  • Danke Dir "Raupi" und Danke an alle Anderen.
    ich habe es nun Anhand des Beispiels so hinbekommen wie ich es mir Vorgestellt habe.
    Habe mit ControlWhrite und meinen Eigenen werten noch ein wenig getestet und es Ging.
    Und, was der Sinn der Sache war, Gelernt hab' ich dabei auch noch was :thumbup:
    An Dieser Stelle wollt ich mal euer Hamergeiles Forum Loben und die ganze hilfreichen Posts.
    So nun genug des Süßholzraspelei :P
    jetzt kann ich 15% schneller Arbeiten als Bisher