Newsgroup: it.comp.programmare.win32
Titolo: Interrompere un ciclo con un pulsante

Chiedo scusa per un eventuale doppio post, ma ho postato due giorni fa e ancora
non lo vedo...
Programmo in BUILDER C++:
Ho una routine assegnata ad un Click di un pulsante che esegue un ciclo while,
come faccio ad interrompere il ciclo premendo un altro pulsante (o lo stesso)
senza aspettare che il ciclo finisca da solo?
Durante tutta l'esecuzione del ciclo non si possono premere altri pulsanti.
Grazie.
-- 
Posted from  [217.57.247.125] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 senza aspettare che il ciclo finisca da solo?
Il modo più semplice è aggiungere un attributo booleano alla classe del tuo
form
e settarlo a true nell'OnClick del pulsante di stop. Quindi nell'altro
OnClick fai
una roba del tipo:
void __fastcall TuoForm::CicloClicked( TObject *owner )
{
    int n = 0;
    Stopped = false;
    // qui disabilita tutti i pulsanti che non possono essere premuti
    while( !Stopped && ...  ) {
        if( n++ >= 50 ) { // per evitare di sprecare CPU se è un ciclo
'stretto'
            n = 0;             // (cioè se fai iterazioni senza delay) 50 è
un esempio,
                                 // metti un valore che ti sembra adeguato
            Application->ProcessMessages();
        }
    }
    // riabilita i pulsanti
}
Bye
     Wiz

 Durante tutta l'esecuzione del ciclo non si possono premere altri
pulsanti.
Devi implementare il ciclo in un thread a parte...in questo modo il sistema
potrà gestire l'interfaccia della tua applicazione...
Ciao
    Riccardo

 altri pulsanti. 
Ti servono un TThread, una variabile globale di tipo TCriticalSection e 
una variabile booleana globale. Dopodichč:
 - derivi una classe TMyLoop (dagli il nome che vuoi) da TThread e
   implementi il suo metodo Execute
 - nel TMyLoop::Execute ci metti il ciclo
 - ogni X ripetizioni (non ad ogni ripetizione perchč diventerebbe
   troppo lento) entri nella sezione critica, controlli la flag e se č
   vera esci dal ciclo, infine esci dalla sezione critica:
extern boolean LoopFlag;
extern TCriticalSection LoopFlagLock;
void TMyLoop::Execute
{
 const int X = 10;
 int i = 0;
 // ciclo
 while(1)
 {
  // ogni X volte prova a...
  if ((i++ % X) == 0) try
  {
   // ... acquisire l'accesso esclusivo alla flag del loop
   LoopFlagLock.Enter();
   // controlla se la flag č vera, se sě esci dal ciclo
   if (LoopFlag)
    break;
  }
  finally
  {
   // infine, rilascia l'accesso esclusivo alla flag globale
   LoopFlagLock.Leave();
  }
  // fai quello che devi fare nel ciclo
 }
}
 - perchč tutto ciň? perchč poi nell'evento click del pulsante tu fai
   questo:
extern boolean LoopFlag;
extern TCriticalSection LoopFlagLock;
void TButton1::OnClick(TObject Sender)
{
 try
 {
  // acquisisci l'accesso esclusivo alla flag
  LoopFlagLock.Enter();
  // setta la flag
  LoopFlag = false;
 }
 finally
 {
  // rilascia l'accesso esclusivo alla flag
  LoopFlagLock.Leave();
 }
}

 writes:
K:H>  - ogni X ripetizioni (non ad ogni ripetizione perchč diventerebbe
K:H>    troppo lento) entri nella sezione critica, controlli la flag e se č
K:H>    vera esci dal ciclo, infine esci dalla sezione critica:
Se  non ti  serve la  precisione al  singolo ciclo  lascia  perdere la
sezione critica e vai a fare un test in lettura sulla variabile un po'
piů spesso.
Se  la locality degli  accessi in  memoria non  č elevata  (ovvero gli
accessi in  memoria sono ben sparsi,  puoi fare il test  anche ad ogni
ciclo.
-- 
Gian Uberto| main(){printf(&unix["\021%six\012\0"],(unix)["have"]+"fun"-0x60);}
Lauri      |                        David Korn, 1987 ioccc best one liner 
(aka saint)|-------------------------------------------------------------------
em@ail: 
sa...@eng.it
 ( vedere X-nospam nello header - see X-nospam in header )

Durante tutta l'esecuzione del ciclo non si possono premere altri pulsanti.
Disabilitali. 
Occhio pero' alle eventuali eccezioni scatenabili nel loop
(usa un costrutto try/try/catch/finally).
-- 
The Follet

Devi implementare il ciclo in un thread a parte...
Non e' strettamente necessario.
-- 
The Follet

una variabile booleana globale. Dopodichč:
Si', poi, coda di rospo, ali di pipistrello e vomito di
coccodrillo ;)
-- 
The Follet

coccodrillo ;)
Fai pure lo spiritoso ;) piuttosto, almeno č corretto il codice che ho 
postato?

 ha scritto nel messaggio
news:3bf123f8...@news.tin.it...

In VC++ ho visto che è necessario...magari BCB implementa già un thread
separato per gestire l'interfaccia oppure esegue un ciclo di lettura dello
stato degli oggetti ogni tot...
Altrimenti come te lo spieghi ? Ogni processo utilizza un solo processore
virtuale...un processo è formato per definizione da istruzioni
sequenziali...quindi uno stesso processore virtuale non può essere
contemporaneamente in porzioni diverse del tuo codice...quindi se
l'applicazione è SingleThreaded non c'è verso modo di fare una cosa del
genere...
Ciao
    Riccardo

modo di fare una cosa del genere...
Ribadisco: non e' vero, vedi la mia soluzione piu'  sotto.
Il  problema  si  risolve  facilmente, in  BCB,  anche  se 
l'applicazione e' a thread singolo.
-- 
Posted from  [80.105.34.80] 


modo di fare una cosa del genere...
Ah no? e i messaggi che ci stanno a fare? :)
Puoi passare periodicamente il controllo al message loop:
 - in VB si fa con DoEvents, che svuota la coda dei messaggi e ritorna
   solo quando sono stati tutti gestiti (e quindi tutte le finestre
   ridisegnate, i click del mouse spediti ai pulsanti, ecc.)
 - in VCL (Delphi e C++ Builder) la stessa identica cosa la si fa con
   Forms.Application.ProcessMessages() (specificare Forms è importante,
   perchè altre unit implementano oggetti globali Application molto
   diversi - ad esempio un cgi-bin difficilmente avrà il bisogno di
   creare delle finestre)
 - in API Win32 pura si usa un loop di GetMessage, TranslateMessage e
   DispatchMessage (vedi il Win32 SDK per del codice d'esempio che
   presenta la forma classica del loop), si ripete finchè GetMessage non 
   ritorna zero
Personalmente però preferisco il multithreading :)

    ritorna zero
Ehm non ci avevo pensato :-)
Comunque credo che farlo due thread sia la soluzione + performante...o
sbaglio ?
Ciao
    Riccardo

sbaglio ?
In questo caso, la soluzione con due thread credo sia quella
meno performante.  Non e' per fare il bastian contrario, ma
credo che significhi cercare di uccidere sempre la solita
formica con il sempre solito cannone.
-- 
The Follet

OK! La soluzione di The Follet funziona perfettamente e nel mio
 caso non influisce in modo dannoso sulla velocita`.
Non litigate piu`!


Non litigate piu`!
E chi litiga ?
-- 
The Follet

> E chi litiga ?
Era una battuta! Comunque Grazie.
