E' una banale form di log di testo, con dentro il bottone da premere.Originariamente inviato da 123delphi321
ciao,
io pensavo fosse la stessa cosa..., e comunque io ho bisogno di premere un pulsante che mi ferma un processo. sia se questo è il download di un file da internet e sia se è il ciclo di elaborazione di una determinata operazione.
in linea generale vorrei capire, una volta per tutte, come funziona questo tipo di funzionamento del thread per poterlo inserire nelle mie procedure dove l'esecuzione di alcuni passi possa essere interrotto dall'operatore.
sto cercando di capire l'esempio che (con tanti ringraziamenti) hai postato...non mi sono chiare alcune cose:
fai riferimento ad un form frmlog in cui c'e' un btnstop ed un memo
poi fai riferimento a delle procedure salvabtnstop ripristinabtnstop che non so cosa facciano..
grazie
Confermo che sono due "cose" estremamente diverse, così come la richiesta, e manca il riferimento all'utilizzo di componenti.
Andiamo per ordine: supponiamo di voler fermare un ciclo, qualsiasi
(un while ad esempio). Un metodo (non "il", ma uno) è quello di utilizzare un componente visuale, ad esempio un bottone, che viene posto in stato enabled=true all'inizio del ciclo.
Dentro il ciclo verifichi se il bottone è enabled: se NON lo è => esci
L'evento del bottone (onclick) sarà, ovviamente, t[speed]button(sender).enabled:=FALSE;
"Ogni tanto" poi ti servirà, nel ciclo, un application.processmessages (in realtà si può ottenere lo stesso effetto in modi diversi, ma certamente tanti esperti ti spiegheranno quali).
Questo forzerà la rilettura della coda dei messaggi windows che sono "parcheggiati" nella form (in sostanza la pressione del bottone).
All'uscita dal ciclo testi se il bottone è enabled: se non lo è => è stato premuto stop e quindi prendi in carico con qualcosa tipo "esecuzione terminata cazzi tuoi".
Puoi aumentare la velocità\aumentare la reattività del bottone STOP a seconda di quanto spesso fai fare il processmessages: più frequenti => più lento.
Un modo "normale" è quello di farlo ogni tot chunk di ciclo
chunk:=numerocicli div 100;
...
if (iterazione mod chunk)=0 then
begin
application.processmessages;
if NOT bottonestop.enabled then break;
end;
Altri approcci sono con un TTIMER, il quale a sua volta crea un vero e proprio thread.
===
Breve introduzione ai thread. Si tratta di pezzi di programma che vengono lanciati parallelamente al thread principale.
Si creano abbastanza facilmente, li si lancia, li si può fermare ("uccidendoli"), abbastanza facilmente anche con la libreria standard.
Quello che non è esattamente banale è sincronizzare i thread tra di loro e, in particolare, l'accesso a risorse condivise, che sono tipicamente i componenti VCL (visuali) e le eventuali strutture dati condivise (chessò un array globale).
Anche qui la faccenda è diverse se vuoi semplicemente fare un thread, e bloccarlo, oppure vuoi sfruttare più thread contemporanei (ad es. più core/CPU).
Nel primo caso la situazione è più semplice, in quanto tipicamente la sequenza del thread principale è
... crea thread
... lancia thread
... FAI QUALCOSA (qui c'è il problema, vedi poi)
... sincronizzati col thread terminato.
Il "fai qualcosa" è il problema, nel senso che puoi mettere a dormire il thread principale, ma devi agire a livello molto basso (non-VCL per capirci), oppure in questo ti serve un ciclo scemo che fa una sorta di busy waiting con l'oppurtuna istruzione per rilasciare rapidamente la CPU in idle.
A livello maggiore di complessità c'è la sincronizzazione vera e propria di thread diversi che, per quanto mi riguarda, uso solo nel caso in cui davvero serva un'elaborazione parallela (ad esempio calcolo di hash su file diversi, quanto piuttosto elaborazione di liste di dati tra di loro indipendenti).
Per questi lavori (ossia "veri") tipicamente utilizzo una libreria (ce ne sono tante) che rendono più agevole operare con tali oggetti.