Seite 1 von 1

foreach Schleife abbrechen

Verfasst: 25.10.2015 13:42
von schleicher
Ich weiß wohl, das man mit break eine Foreach Schleife abbrechen kann, aber wie funktioniert das im Window mit einem Button ?
Wie in meinem Beispielcode zu sehen habe ich es mit einer Variable(abbrechen=1) versucht, aber diese Variable scheint während die Foreach-Schleife läuft, nicht geändert zu werden. (Das kopieren von Ordnern geht natürlich auch mit CopyDirectory(, der Code ist nur ein Beispiel)
Ich habe in dem Beispiel ein Delay eingesetzt, damit das Ganze nicht so schnell abläuft. Ist in meinem eigentlichen Code nicht drin.

Code: Alles auswählen

EnableExplicit

Structure copyfiles
  Datei.s
  Pfad.s
  Komplettpfad.s
  Size.l
EndStructure
Global NewList copyfiles.copyfiles()



Enumeration FormWindow
  #Window_testcopy
EndEnumeration

Enumeration FormGadget
  #ProgressBar_copy
  #String_Copyinfo
  #Button_Abbrechen
  #String_Ursprung
  #Button_Ursprung
  #String_Ziel
  #Button_Ziel
  #Button_copy
EndEnumeration

Declare CopyFolder()


Global abbrechen, Ordner_Ursprung.s, Ordner_Ziel.s, gesamtkbyte.l, anzahl

OpenWindow(#Window_testcopy, 0, 0, 450, 240, "Test Ordner kopieren", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ProgressBarGadget(#ProgressBar_copy, 20, 100, 400, 25, 0, 0)
StringGadget(#String_Copyinfo, 20, 140, 400, 25, "")
ButtonGadget(#Button_Abbrechen, 300, 190, 120, 25, "Abbrechen")
StringGadget(#String_Ursprung, 20, 20, 170, 25, "zu kopierender Ordner")
ButtonGadget(#Button_Ursprung, 190, 20, 30, 25, "..")
StringGadget(#String_Ziel, 240, 20, 150, 25, "Zielordner")
ButtonGadget(#Button_Ziel, 390, 20, 30, 25, "..")
ButtonGadget(#Button_copy, 20, 190, 130, 25, "Kopiere")


Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
      
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget()
          
        Case #Button_Ursprung
          gesamtkbyte=0
          anzahl=0
          Ordner_Ursprung=PathRequester("Bitte Ordner zum kopieren wählen", "c:\")
          SetGadgetText(#String_Ursprung, Ordner_Ursprung)
          
          If ExamineDirectory(0, Ordner_Ursprung, "*.*")
            While NextDirectoryEntry(0)
              If DirectoryEntryType(0) = #PB_DirectoryEntry_File
                AddElement(copyfiles())
                copyfiles()\Komplettpfad=Ordner_Ursprung+DirectoryEntryName(0)
                copyfiles()\Datei=DirectoryEntryName(0)
                copyfiles()\Pfad=Ordner_Ursprung
                copyfiles()\Size=DirectoryEntrySize(0)/1024
                gesamtkbyte+copyfiles()\Size
                anzahl+1
              EndIf
            Wend
            FinishDirectory(0)
          EndIf
          
        Case #Button_Ziel
          Ordner_Ziel=PathRequester("Bitte Zielordner wählen", "c:\")
          SetGadgetText(#String_Ziel, Ordner_Ziel)
        Case #Button_copy
          abbrechen=0
          CopyFolder()
        Case #Button_Abbrechen
          abbrechen=1
          
      EndSelect
  EndSelect
  
ForEver



Procedure CopyFolder()
  Define Ordnername_Ursprung.s, anzahl_backslash, File.s, size_copy.l, x
  size_copy=0
  
  If Ordner_Ursprung
    anzahl_backslash=CountString(Ordner_Ursprung, "\")
    Ordnername_Ursprung=StringField(Ordner_Ursprung, anzahl_backslash, "\")
    Debug "Ordnername = "+Ordnername_Ursprung
  EndIf
  
  SetGadgetAttribute(#ProgressBar_copy, #PB_ProgressBar_Maximum, gesamtkbyte) 
  
  If Ordner_Ziel And Ordner_Ursprung
    If FileSize(Ordner_Ziel+Ordnername_Ursprung)-1
      CreateDirectory(Ordner_Ziel+Ordnername_Ursprung)
    EndIf
    x=1
    ForEach copyfiles()
      Delay(1000)
      While WindowEvent() :Wend
      File=copyfiles()\Komplettpfad
      size_copy+copyfiles()\Size 
      If File
        If abbrechen=0
          If CopyFile(File, Ordner_Ziel+Ordnername_Ursprung+copyfiles()\Datei)<>0
            SetGadgetState(#ProgressBar_copy, size_copy)
            SetGadgetText(#String_Copyinfo, "Kopiere : "+x+"/"+anzahl+" "+File)
            If x=anzahl
              SetGadgetState(#ProgressBar_copy, 0)
              SetGadgetText(#String_Copyinfo, "Fertig")
              EndIf
          EndIf
        Else
          Break
        EndIf
      EndIf
      x+1
    Next
  Else
    MessageRequester("Error", "Bitte Ursprungs und Zielordner wählen !")
  EndIf
EndProcedure

Re: foreach Schleife abbrechen

Verfasst: 25.10.2015 14:30
von STARGÅTE
In dem moment wo du CopyFolder() aufrufst, läuft der Code ja nur noch im unteren Prozedurblock.
Dein ganzer Window-Event-Block wird dabei nicht mehr abgearbeitet, erst wenn CopyFolder() fertig ist.

Es gibt nun zwei möglichkeiten:
  • Du erstellt aus CopyFolder() einen Thread der parallel gestartet wird, dann wird dein Event-Block weiter bearbeitet und abbrechen kann verändert und überprüft werden. (Erfordert Thread-Safe zusammen mit absicherung von Variablen/Listen die in beiden Codeteilen benutzt werden)
  • Du erstellt auch in der ForEach-Schleife unten ein Window-Event Block, der dann separat den Abbrechen-Button abfragt und dann dort auf abbrechen = 1 stellst.

Re: foreach Schleife abbrechen

Verfasst: 25.10.2015 14:43
von schleicher
STARGÅTE hat geschrieben: Du erstellt auch in der ForEach-Schleife unten ein Window-Event Block, der dann separat den Abbrechen-Button abfragt und dann dort auf abbrechen = 1 stellst.
Danke für den Tip. Probiere das gleich mal aus.
Funktioniert ! Ist aber bestimmt noch besser zu schreiben oder ?

Code: Alles auswählen

EnableExplicit

Structure copyfiles
  Datei.s
  Pfad.s
  Komplettpfad.s
  Size.l
EndStructure
Global NewList copyfiles.copyfiles()



Enumeration FormWindow
  #Window_testcopy
EndEnumeration

Enumeration FormGadget
  #ProgressBar_copy
  #String_Copyinfo
  #Button_Abbrechen
  #String_Ursprung
  #Button_Ursprung
  #String_Ziel
  #Button_Ziel
  #Button_copy
EndEnumeration

Declare CopyFolder()


Global abbrechen, Ordner_Ursprung.s, Ordner_Ziel.s, gesamtkbyte.l, anzahl

OpenWindow(#Window_testcopy, 0, 0, 450, 240, "Test Ordner kopieren", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
ProgressBarGadget(#ProgressBar_copy, 20, 100, 400, 25, 0, 0)
StringGadget(#String_Copyinfo, 20, 140, 400, 25, "")
ButtonGadget(#Button_Abbrechen, 300, 190, 120, 25, "Abbrechen")
StringGadget(#String_Ursprung, 20, 20, 170, 25, "zu kopierender Ordner")
ButtonGadget(#Button_Ursprung, 190, 20, 30, 25, "..")
StringGadget(#String_Ziel, 240, 20, 150, 25, "Zielordner")
ButtonGadget(#Button_Ziel, 390, 20, 30, 25, "..")
ButtonGadget(#Button_copy, 20, 190, 130, 25, "Kopiere")


Repeat
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
      End
      
    Case #PB_Event_Menu
      Select EventMenu()
      EndSelect
      
    Case #PB_Event_Gadget
      Select EventGadget()
          
        Case #Button_Ursprung
          gesamtkbyte=0
          anzahl=0
          Ordner_Ursprung=PathRequester("Bitte Ordner zum kopieren wählen", "c:\")
          SetGadgetText(#String_Ursprung, Ordner_Ursprung)
          
          If ExamineDirectory(0, Ordner_Ursprung, "*.*")
            While NextDirectoryEntry(0)
              If DirectoryEntryType(0) = #PB_DirectoryEntry_File
                AddElement(copyfiles())
                copyfiles()\Komplettpfad=Ordner_Ursprung+DirectoryEntryName(0)
                copyfiles()\Datei=DirectoryEntryName(0)
                copyfiles()\Pfad=Ordner_Ursprung
                copyfiles()\Size=DirectoryEntrySize(0)/1024
                gesamtkbyte+copyfiles()\Size
                anzahl+1
              EndIf
            Wend
            FinishDirectory(0)
          EndIf
          
        Case #Button_Ziel
          Ordner_Ziel=PathRequester("Bitte Zielordner wählen", "c:\")
          SetGadgetText(#String_Ziel, Ordner_Ziel)
        Case #Button_copy
          abbrechen=0
          CopyFolder()
        
          
      EndSelect
  EndSelect
  
ForEver



Procedure CopyFolder()
  Define Ordnername_Ursprung.s, anzahl_backslash, File.s, size_copy.l, x, Event, a
  size_copy=0
  
  If Ordner_Ursprung
    anzahl_backslash=CountString(Ordner_Ursprung, "\")
    Ordnername_Ursprung=StringField(Ordner_Ursprung, anzahl_backslash, "\")
    Debug "Ordnername = "+Ordnername_Ursprung
  EndIf
  
  SetGadgetAttribute(#ProgressBar_copy, #PB_ProgressBar_Maximum, gesamtkbyte) 
  
  If Ordner_Ziel And Ordner_Ursprung
    
    If FileSize(Ordner_Ziel+Ordnername_Ursprung)-1
      CreateDirectory(Ordner_Ziel+Ordnername_Ursprung)
    EndIf
    x=1
    ForEach copyfiles()
      ;Delay(1000)
      While WindowEvent() :Wend
      File=copyfiles()\Komplettpfad
      size_copy+copyfiles()\Size 
      If File
        If abbrechen=0
          If CopyFile(File, Ordner_Ziel+Ordnername_Ursprung+copyfiles()\Datei)<>0
            SetGadgetState(#ProgressBar_copy, size_copy)
            SetGadgetText(#String_Copyinfo, "Kopiere : "+x+"/"+anzahl+" "+File)
            If x=anzahl
              SetGadgetState(#ProgressBar_copy, 0)
              SetGadgetText(#String_Copyinfo, "Fertig")
              EndIf
          EndIf
        Else
          SetGadgetState(#ProgressBar_copy, 0)
          SetGadgetText(#String_Copyinfo, "Abbruch durch Benutzer ! Kopiert wurden "+Str(x)+" von "+Str(anzahl)+ " Dateien :")
       
          Break
        EndIf
      EndIf
      x+1
      a=0
      Repeat
        Event=WaitWindowEvent()
        If Event=#PB_Event_Gadget
          If EventGadget()=#Button_Abbrechen
            abbrechen=1  
         EndIf
        EndIf
        a+1
     Until a>3
      
      
      
    Next
  Else
    MessageRequester("Error", "Bitte Ursprungs und Zielordner wählen !")
  EndIf
EndProcedure

Re: foreach Schleife abbrechen

Verfasst: 25.10.2015 16:01
von NicTheQuick
Dritte Möglichkeit: Du nutzt BindGadgetEvent() für den "Abbrechen"-Button. Damit kann eine Procedure gestartet werden, sobald du auf den Button klickst, die die "abbrechen"-Variable auf 1 setzt. Aber trotzdem musst du hierfür mindestens ein "While WindowEvent() : Wend" in der Kopierprozedur einbauen.

Re: foreach Schleife abbrechen

Verfasst: 25.10.2015 16:27
von schleicher
NicTheQuick hat geschrieben:Dritte Möglichkeit: Du nutzt BindGadgetEvent() für den "Abbrechen"-Button.
Daran hatte ich auch schon gedacht, aber ich bin mit der 2.Variante schonmal zufrieden.Danke