Abbruch einer längeren Aktion

Sonstiges (nicht kategorisierbar)

Moderator: Moderatoren

Antworten
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Abbruch einer längeren Aktion

Beitrag von UliTs »

Hallo Allerseits,

in einem meiner GUI-Dialoge kann der Anwender nach Klicken auf einen Button eine längere Zeit dauernde Aktion starten.
Die zugehörige Routine sieht z.B. so aus:

Code: Alles auswählen

do while .not. oTable:EOF
  ...
  oTable:skip(1)
enddo
Wie programmiere ich es am geschicktesten, daß der Anwender die Aktion (wenn sie ihm zu lang dauert) abbrechen kann?
a) wie mittels Tastendruck
b) wie mittels eines zusätzlichem Button im Dialog?

Uli
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Benutzeravatar
brandelh
Foren-Moderator
Foren-Moderator
Beiträge: 15689
Registriert: Mo, 23. Jan 2006 20:54
Wohnort: Germersheim
Hat sich bedankt: 65 Mal
Danksagung erhalten: 33 Mal
Kontaktdaten:

Re: Abbruch einer längeren Aktion

Beitrag von brandelh »

Zunächst muss man unterscheiden ob die Aktion im normalen Thread läuft oder einen eigenen hat.
Ein eigener Thread muss man per Signal oder Event zum Abbruch bringen ... das führt jetzt zu weit.


Wenn alles in einem Thread abläuft und GUI=YES ist, hast du hier ein Problem mit der Eventverarbeitung.
Unter Clipper und XBase ohne GUI würde man einfach ein INKEY(1) integrieren und diese Taste abfragen ...
mit GUI geht das so direkt nicht (es sind zu viele Events).

Zuerst die Eventloop erreichbar machen:
in Main wurde die Schleife durch eine Funktion ersetzt:

Code: Alles auswählen

 
   in main:
   ...
            // Das Programm wird in AppQuit() abgebrochen
            DoEventLoop()    // Aufruf ohne Endeparameter !
   ...
   Funktion:
*-----------------------------------------------------------------------------
FUNCTION DoEventLoop(nSeconds)               // For Next Schleifen unterbrechen und Events verarbeiten !
   local nBisSeconds, nEvent, mp1, mp2, oXbp

   DEFAULT nSeconds to 0                     // Standard ist endlose Ausfhrung

   nBisSeconds := seconds() + nSeconds

   DO WHILE .T.
      nEvent := AppEvent( @mp1, @mp2, @oXbp, nSeconds)
      do case
         case nEvent = xbe_None
            * nichts tun ist hier Standard
         case nEvent = xbeP_Keyboard .and. mp1 == xbeK_F1
                       * xbeP_HelpRequest erscheinen fr jede Xbp Instanz, also zu oft !
                       MsgBox("Die Hilfe ist fr dieses Programm noch nicht erstellt.")
         otherwise
              oXbp:handleEvent( nEvent, mp1, mp2 )
      endcase
      if nSeconds > 0 .and. nBisSeconds < seconds() // nur wenn keine endlose Ausfhrung
         exit
      endif
   ENDDO
return nil
In beiden Fällen muss man dafür sorgen, dass Events auch in Endlosschleifen verarbeitet werden.
Man braucht eine FLAG (Funktion, Variable, Object ...)

Code: Alles auswählen

IsAbbruch(.f.) // wir merken uns kein Abbruch
do while .not. oTable:EOF
  ...
  DoEventLoop(0.01) // 1/100 Sekunde die Oberfläche bedienen !
*  if LastAppEvent()  ???? in 0.01 Sekunden werden hunderte  Events verarbeitet ... 
*                                  ich glaube nicht dass diese hier Sinn machen würde.
*                                  In der Eventloop könnte man eine generelle Abbruchsituation 
*                                  vorsehen, aber diese ist auf das Fenster begrenzt.
  if IsAbbruch()
     exit
  endif
  oTable:skip(1)  
enddo
function IsAbbruch(lCancel)
    local IsToStop := .f.
    if lCancel # NIL
       IsToStop := lCancel
    endif
return IsToStop
So jetzt müssen wir eine Möglichkeit einbauen den Zustand der FLAG zu ändern:

Pushbutton:
oPB_BrichsEinfachAb:activate := {|| IsAbbruch(.t.) }

oder Keyboard:

oDLG:keyboard := {|nKeyCode, uNil, oXbp| iif(nKeyCode=MeinKillerCode, IsAbbruch(.t.) , nil) }

so müsste es gehen. In der Abbruchfunktion sollte eventuell noch eine Sicherheitsabfrage enthalten sein
und du mußt natürlich sicherstellen, dass ein Abbruch ohne böse Folgen bleibt ;-)
Befehle wie COPY TO etc. können so natürlich nicht abgebrochen werden ...
Gruß
Hubert
Antworten