Gambas-it

Gambas3 => Programmazione => Topic aperto da: kicco - 11 Agosto 2020, 13:38:01

Titolo: Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 11 Agosto 2020, 13:38:01
Ho la necessità di interrompere l'esecuzione di una Subroutine esternamente alla Sub stessa.
Nel mio caso: dal Form_close devo interrompere una Sub prima di uscire dal programma.
Prima che vuott mi cazzi!  :P
la domanda specifiche è: esiste un comando diretto che permetta questo?
STOP EVENT si può usare solo all'interno della sub  (ovviamente).
Altri non ne ho trovati!
 :ciao:
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: cogier - 11 Agosto 2020, 15:09:59
Questo aiuterà?

Codice: [Seleziona]
bStop As Boolean

Public Sub Form_Open()

  Me.Show
  Wait 0.25
  Start

End

Public Sub Start()

  Dim iInt As Integer

  Do
    Inc iInt
    Wait 0.5
    Print iInt
    If bStop = True Then Return
  Loop

End

Public Sub Form_Close()

  bStop = True

End
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 11 Agosto 2020, 15:57:00
Nel mio caso: dal Form_close devo interrompere una Sub prima di uscire dal programma.
Puoi qui incollare quella sub-routine da interrompere ?
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 11 Agosto 2020, 18:32:43
Questo aiuterà?

Codice: [Seleziona]
bStop As Boolean

Public Sub Form_Open()

  Me.Show
  Wait 0.25
  Start

End

Public Sub Start()

  Dim iInt As Integer

  Do
    Inc iInt
    Wait 0.5
    Print iInt
    If bStop = True Then Return
  Loop

End

Public Sub Form_Close()

  bStop = True

End
Grazie Cogier, anch'io avevo pensato ad una soluzione analoga.
Speravo esistesse un comando specifico.
 :-*
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 11 Agosto 2020, 18:36:54
Nel mio caso: dal Form_close devo interrompere una Sub prima di uscire dal programma.
Puoi qui incollare quella sub-routine da interrompere ?
Urka!
Devo vedere se riesco a ripulirla perchè è un po' complessa!
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 11 Agosto 2020, 23:47:08
Rispondo al quesito iniziale: Esiste un comando specifico che permetta di interrompere l'esecuzione di un ciclo al di fuori del ciclo che gestisce l'evento stesso?
Risposta:NO!

La mio domanda nasceva dal fatto che chiudendo un programma che al suo interno prevede un ciclo che può durare anche 40s, si chiudeva tutto, la seriale, tutti i Form, ma il programma rimaneva "appeso" perchè il ciclo di 40s era ancora attivo.

Ho risolto ponendo dopo il Me.close ( Nel Form_open ho attivato Application.MainWindow = Me) l'istruzione Quit che interrompe l'Event Loop e quindi anche la subroutine incriminata permettendo la chiusura pulita.
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 12 Agosto 2020, 00:31:43
Se non inserisci qui un semplice codice che ripropone in modo essenziale e breve le routine e le righe di comando fondamentali, non si potrà capire perfettamente la questione da te posta, né cercare una soluzione.
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: Gianluigi - 12 Agosto 2020, 10:07:17
Rispondo al quesito iniziale: Esiste un comando specifico che permetta di interrompere l'esecuzione di un ciclo al di fuori del ciclo che gestisce l'evento stesso?
Risposta:NO!

La mio domanda nasceva dal fatto che chiudendo un programma che al suo interno prevede un ciclo che può durare anche 40s, si chiudeva tutto, la seriale, tutti i Form, ma il programma rimaneva "appeso" perchè il ciclo di 40s era ancora attivo.

Ho risolto ponendo dopo il Me.close ( Nel Form_open ho attivato Application.MainWindow = Me) l'istruzione Quit che interrompe l'Event Loop e quindi anche la subroutine incriminata permettendo la chiusura pulita.

Beh, vista la tua soluzione avresti dovuto rispondere si è Quit.

Quit interrompe sempre un programma, ma quasi mai è una buona soluzione per i programmi grafici, perché lascia in giro parecchie scorie.
Mi sembra strano che la tua console non migugni...

 :ciao:
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 12 Agosto 2020, 10:27:38
Quit interrompe sempre un programma, ma quasi mai è una buona soluzione per i programmi grafici, perché lascia in giro parecchie scorie.
Infatti la guida ufficiale consiglia l'uso dell'istruzione "Quit" per i programmi a riga di comando.
Un esempio semplice può essere quello di interrompere l'Evento "Application_Read()", consentendo al programma di chiudersi:
Codice: [Seleziona]
Private i As Integer
Private bo As Boolean


Public Sub Main()

  Repeat
    Inc i
    Print i
    Wait 0.3
  Until bo == True
 
  Quit    ' Fa sì che il programma sia terminato
 
End


' Cliccando sul tasto "Invio" della tastiera, si scatena questo Evento:
Public Sub Application_Read()
 
  bo = True
 
End

Poiché estremamente radicale, a mio avviso Quit va usato solo come "extrema ratio" per chiudere un programma altrimenti non terminabile.
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 12 Agosto 2020, 11:00:03
Ripeto comunque la necessità che kicco mostri il codice (o una riproduzione essenziale delle routine e dei comandi fondamentali del codice originario), giacché - diversamente - alla sua domanda sulla eventuale esistenza di un "comando unico", se posta con finalità didattica, la soluzione di cogier può essere soddisfacente.
Sappiamo, però, che i cicli posseggono soluzioni proprie, "condizionali", previste appunto per soddisfare la richiesta di uscita; e di norma andrebbero usate quelle.

Infatti in un programma grafico l'uscita dal ciclo, effettuata mediante le previste modalità "condizionali" e causata dalla chiusura arbitraria della finestra principale del programma, non pregiudica in via generale il termine del programma medesimo, rendendo così inutile ed eccessivo l'uso dell'istruzione "Quit":
Codice: [Seleziona]
Private b As Byte


Public Sub Form_Open()
 
  Me.Show
 
  Ciclo()
 
End


Private Procedure Ciclo()
 
  Repeat
    Inc b
    Print b
    Wait 0.3
  Until b == 100
 
End


Public Sub Form_Close()   ' Chiudendo il Form, si scatena questo Evento
 
  b = 100
 
End

In vero, l'uso di "Return", già proposto da cogier, risulta necessario, qualora dopo il ciclo vi siano altre righe di comando che in caso di uscita arbitraria dal ciclo, ottenuta con la chiusura forzata del Form, si intenda non far processare (quindi da saltare).
Ciò conferma che l'uso dell'istruzione "Return" determina, non solo - nel caso di specie - l'uscita dal ciclo, ma anche l'abbandono immediato e definitivo  della sub-routine, ove essa è posta.

A tal riguardo si provino i seguenti codici.
Senza "Return" nel ciclo:
Codice: [Seleziona]
Private b As Byte


Public Sub Form_Open()
 
  Me.Show
 
  Ciclo()
 
End


Private Procedure Ciclo()
 
  Repeat
    Inc b
    Print b
    Wait 0.3
  Until b == 100
 
  Print "Riga di comando successiva al ciclo"
 
End


Public Sub Form_Close()
 
  b = 100
 
End

Con "Return" nel ciclo per l'uscita immediata e definitiva dalla sub-routine:
Codice: [Seleziona]
Private b As Byte


Public Sub Form_Open()
 
  Me.Show
 
  Ciclo()
 
End


Private Procedure Ciclo()
 
  Repeat
    Inc b
    Print b
    If b > 100 Then Return
    Wait 0.3
  Until b == 100
 
  Print "Riga di comando successiva al ciclo"
 
End


Public Sub Form_Close()
 
  b = 200
 
End
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 12 Agosto 2020, 17:40:49
Se non inserisci qui un semplice codice che ripropone in modo essenziale e breve le routine e le righe di comando fondamentali, non si potrà capire perfettamente la questione da te posta, né cercare una soluzione.
Eccolo:
Codice: [Seleziona]
Private fFlag As Boolean

Public Sub BtFalse_Click()

  fFlag = False

End

Public Sub BtTrue_Click()

  fFlag = True

End

Public Sub BtStart_Click()

  Dim i As Integer
  Dim ia As Integer

  For i = 0 To 200
    Print "Ciclo Principale " & i

    For ia = 1 To 30
      If fFlag = True Then
        Break
        fFlag = False
      Endif
      Wait 1
    Next

    If fFlag = False Then
      Print "Scaduti i 30s"
    Endif
    fFlag = False

  Next

  fFlag = False

End
Premetto che non ho ancora provato i codici che hai proposto...
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 12 Agosto 2020, 17:46:46
Rispondo al quesito iniziale: Esiste un comando specifico che permetta di interrompere l'esecuzione di un ciclo al di fuori del ciclo che gestisce l'evento stesso?
Risposta:NO!

La mio domanda nasceva dal fatto che chiudendo un programma che al suo interno prevede un ciclo che può durare anche 40s, si chiudeva tutto, la seriale, tutti i Form, ma il programma rimaneva "appeso" perchè il ciclo di 40s era ancora attivo.

Ho risolto ponendo dopo il Me.close ( Nel Form_open ho attivato Application.MainWindow = Me) l'istruzione Quit che interrompe l'Event Loop e quindi anche la subroutine incriminata permettendo la chiusura pulita.

Beh, vista la tua soluzione avresti dovuto rispondere si è Quit.

Quit interrompe sempre un programma, ma quasi mai è una buona soluzione per i programmi grafici, perché lascia in giro parecchie scorie.
Mi sembra strano che la tua console non migugni...

 :ciao:
Lo so che Quit non va usato per uscire dai programmi grafici.
Ho usato infatti Me.close dopo aver messo Application.MainWindow = Me nel Form_open.
Solo dopo ho usato Quit
Magari potrei mettere un wait tra i due per attendere che tutti i Form siano chiusi correttamente.
Codice: [Seleziona]
Public Sub Form_Close()
     ....
     .... 
      Me.close
      Quit

End
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 12 Agosto 2020, 17:51:12
Premetto che non ho ancora provato i codici che hai proposto...

Hanno l'intenzione di essere meramente didattici.
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 12 Agosto 2020, 20:20:19
Allego un progetto che mima la situazione che vi descrivevo.
Col tasto START si avvia il programma.
Con TRUE e FALSE si può intervenire sui cicli.
Con Esci ovviamente si esce,ma vedrete che nell'IDE il programma non si chiude.
Spero che questo chiarisca!
 :ciao:
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 12 Agosto 2020, 20:28:27
Dunque, l'intento di kicco è quello di far terminare il programma, quando viene chiusa arbitrariamente la finestra principale.
Per fare ciò, deve assicurarsi che il controllo del processo esca dai due cicli, previsti dalla routine "BtStart_Click()".
 
Riprendo il codice esemplificativo di kicco, tentando di risolvere il problema con l'uso delle modalità "condizionali", previste dagli specifici cicli, evitando quindi l'uso della ghigliottina "Quit".

Codice: [Seleziona]
Private fFlag As Boolean
Private i As Integer


Public Sub BtTrue_Click()

  fFlag = True

End

Public Sub BtStart_Click()
 
  Dim ia As Integer
 
  Repeat
    Print "Ciclo Principale " & i
 
    ia = 1

    While (ia < 30) And (fFlag == False)
      Wait 1
      Inc ia
    Wend

    If fFlag = False Then Print "Scaduti i 30s\n"
    fFlag = False
    Inc i
  Until i > 200
 
  Print "Uscito dal ciclo principale"

End

Public Sub BtExit_Click()

  Me.Close

End

Public Sub Form_Close()

  fFlag = True
  i = 255

End
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: Gianluigi - 12 Agosto 2020, 23:17:44
Quello che mi lascia un po perplesso nel codice di kicco è che pur essendoci una sola finestra, abbia inserito questo codice:
Codice: [Seleziona]
Public Sub Form_Open()

  Application.MainWindow = Me

End

kicco non è che ne stai fraintendendo il significato?

È la stessa cosa che se tu avessi altre due finestre aperte (Form1 e Form2) e scrivessi in FMain:

Codice: [Seleziona]
Public Sub Form_Close()

  Form1.Close
  Form2.Close

End

Anche se può apparire banale, faccio un'altra precisazione: il codice di vuott deve stare nell'evento Close della finestra che contiene il ciclo.

 :ciao:
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 12 Agosto 2020, 23:24:01
...il codice di vuott deve stare nell'evento Close della finestra che contiene il ciclo.

Senza specifica e diversa indicazione ho ritenuto che il codice di kicco prevedesse un solo Form.
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 13 Agosto 2020, 09:24:52
Quello che mi lascia un po perplesso nel codice di kicco è che pur essendoci una sola finestra, abbia inserito questo codice:
Codice: [Seleziona]
Public Sub Form_Open()

  Application.MainWindow = Me

End

kicco non è che ne stai fraintendendo il significato?

È la stessa cosa che se tu avessi altre due finestre aperte (Form1 e Form2) e scrivessi in FMain:

Codice: [Seleziona]
Public Sub Form_Close()

  Form1.Close
  Form2.Close

End

Anche se può apparire banale, faccio un'altra precisazione: il codice di vuott deve stare nell'evento Close della finestra che contiene il ciclo.

 :ciao:
Nel Programma reale ci sono altre Form e uso proprio quel trucco che ho imparato da te per chiuderle tutte.
Nel caso dell'esempio ovviamente non sarebbe utile.
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 13 Agosto 2020, 09:51:31
Ho corretto la routine del Test1 per renderla più simile all'originale aggiungendo un Wait 5.
Questo perchè applicando sostanzialmente l'esempio di cogier e controllando il flag che forza il Return sia del ciclo principale che dei cicli interni a quello principale, durante quel wait la routine rimane insensibile fino allo scadere dello stesso.
Vedi Test2_a.
Ho dovuto, per risolvere il problema usare al posto del Wait 5, cinque cicli For con un tempo di attesa di 1s controllando il flag ad ogni ciclo e quindi l'eventuale Return.
Vedi Test2_b.
Certo con Quit si risolve tutto anche se con effetto "ghigliottina" con messaggi vari in consolle che sostanzialmente, correggimi Gianluigi, indicano solo che un ciclo era ancora in essere! Non potremmo considerarlo "fisiologico"?
Ti prego, parlami ancora dopo questa affermazione!  :P
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: Gianluigi - 13 Agosto 2020, 10:33:24
Ho corretto la routine del Test1 per renderla più simile all'originale aggiungendo un Wait 5.
Questo perchè applicando sostanzialmente l'esempio di cogier e controllando il flag che forza il Return sia del ciclo principale che dei cicli interni a quello principale, durante quel wait la routine rimane insensibile fino allo scadere dello stesso.
Vedi Test2_a.
Ho dovuto, per risolvere il problema usare al posto del Wait 5, cinque cicli For con un tempo di attesa di 1s controllando il flag ad ogni ciclo e quindi l'eventuale Return.
Vedi Test2_b.
E questo nuovo codice dove lo hai nascosto?
 :mad:
Citazione
Certo con Quit si risolve tutto anche se con effetto "ghigliottina" con messaggi vari in consolle che sostanzialmente, correggimi Gianluigi, indicano solo che un ciclo era ancora in essere! Non potremmo considerarlo "fisiologico"?
:violent:
Citazione
Ti prego, parlami ancora dopo questa affermazione! 

 >:(   :D  :ciao:
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 13 Agosto 2020, 10:38:05
Citazione
E questo nuovo codice dove lo hai nascosto?
:hard: L'ho allegato adesso al Post!  :-[ :-[ :-[
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: Gianluigi - 13 Agosto 2020, 11:07:29
Citazione
E questo nuovo codice dove lo hai nascosto?
:hard: L'ho allegato adesso al Post!  :-[ :-[ :-[
:D

Scaricato, più tardi ci do un'occhiata  :ciao:
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: Gianluigi - 13 Agosto 2020, 11:56:11

Ho dovuto, per risolvere il problema usare al posto del Wait 5, cinque cicli For con un tempo di attesa di 1s controllando il flag ad ogni ciclo e quindi l'eventuale Return.
Vedi Test2_b.


Perché secondo te il test b funziona?

Hai provato a chiudere il form dal pulsante della barra?

Qui ci vorrebbe proprio una gif di vuott   :-\
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: Gianluigi - 13 Agosto 2020, 13:42:27
Sarò stupido ma non mi è molto chiaro cosa rappresenta la bandierina effe e perché possa essere governata dai pulsanti.

Comunque se vuoi che funzioni, togli il codice da open e  BtExit e mettilo in close così, come ti era già stato suggerito:

Codice: [Seleziona]
Public Sub Form_Close()

  Application.MainWindow = Me
  bFlag = True

End

Public Sub BtExit_Click()

  Me.close

End

Poi se vuoi che fFlag cambi in false spostalo da dopo il Break e mettilo prima.

Comunque mi sembrava più stimolante il codice di vuott...
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: vuott - 13 Agosto 2020, 13:58:38
Comunque mi sembrava più stimolante il codice di vuott...

(https://i.pinimg.com/originals/69/19/7f/69197f92c7370405c8914c81bca88028.gif)
Titolo: Re:Come Interrompere l'esecuzione di una Sub
Inserito da: kicco - 13 Agosto 2020, 15:05:55
Sarò stupido ma non mi è molto chiaro cosa rappresenta la bandierina effe e perché possa essere governata dai pulsanti.
Tieni conto che il codice è una riduzione di una routine "reale". La bandierina effe rappresenta un evento esterno provocato da dati seriali.