Newsgroup: it.comp.lang.delphi
Titolo: Alternative per fare polling ?

Ciao a tutti,
su una funzione devo attendere un evento:
while(isWorking) do Application.ProcessMessages;
Questo pero' fa schizzare la cpu al 100%.
Ci sono metodi alternativi a questo ?
Grazie.
Fulvio
===========================================
To reply, remove LEVAME
My digital photos: 
http://www.alecab.it/cai

potresti provare a creare un thread con priorità bassissima (idle) che
esegue un ciclo in cui non fa niente se non testare il isWorking...


 while(isWorking) do Application.ProcessMessages;
L'alternativa e' usare un secondo thread e
un oggetto di sincronizzazione tra i due.
Nel primo thread resetti l'oggetto di sincronizzazione
(che puo' essere benissimo un TEvent).
Attivi il secondo thread e ti metti in wait 
sull'oggetto.  Quando il secondo thread finisce
di compiere l'elaborazione, setta l'oggetto,
ponendolo in stato segnalato e facendo, quindi,
terminare l'attesa al primo thread.
L'attesa su un oggetto come TEvent racchiude
una chiamata a WaitForSingleObject che, per
come e' fatta, consuma pochissime risorse.
Se vuoi un esempio, scrivimi in privato.
-- 
Posted from  [80.105.34.80] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

 Ci sono metodi alternativi a questo ?
Oltre a WaitForSingle(Multiple)Object(s)(Ex), adatto per TEvent,
WaitableTimer e simili (v. msdn o Win32.hlp) puoi piu' semplicemente
usare Sleep(0) o Sleep(5):
while (shouldWait) do begin
  Application.ProcessMessages;
  Sleep(5);
end;
Saluti
Paolo Arosio

> while(isWorking) do Application.ProcessMessages;
(dirty trick..)
while(isWorking) do
begin
  Application.ProcessMessages;
  Sleep(1);
end;
Ciao,
-=SIMO=-

 end;
non mi sembra ideale bloccare il thread ad intervalli di 5 millisecondi ...
più corretto, a mio avviso, decentrare il codice in un secondo thread con
priorità bassa.
--
- Carlo -
c.b...@libero.it

 priorità bassa.
Concordo, tra l'altro la soluzione che sfrutta il while 
e' concettualmente sbagliata.  Il while con uno Sleep(0) 
o comunque con uno Sleep di pochi millisecondi va bene
quando c'e' *comunque* un secondo thread.  Serve, cioe'
a simulare una bassa priorita'.  Sleep(0), difatti, 
comunica al sistema che il thread in questione non ha
piu' intenzione di sfruttare il tempo rimanente del
time-slice assegnatogli e quindi il sistema e' autorizzato
ad attivare il secondo thread.  Scrivere un ciclo come
quello di sopra fa si' che l'aggiornamento di shouldWait
debba essere fatto sempre mediante un evento del sistema 
(un messaggio, per intenderci) perche' l'unico punto di
fuga e' il ProcessMessages.  Questo vuol dire che
in un'applicazione mono-thread, e' comunque un secondo
thread a dover fermare il ciclo, dove con "thread" si
intende o la mano dell'utente che clicca su un pulsante, 
o un'applicazione esterna che manda un messaggio.


 debba essere fatto sempre mediante un evento del sistema
Non e' evidente dal codice, ma shouldWait puo' essere una funzione che,
ad es, va a vedere se una pipe ha raggiunto una certa dimensione (oppure
e' stato creato un file su disco, o qualunque altra cosa).
Al limite, shouldWait stessa esegue parte dell'operazione (lunga ma che
non si vuole congeli l'UI).
Sul fatto poi che il tutto sia q&d posso anche essere d'accordo, cmq il
"processore al 100%" dovrebbe essere superato con la sleep.
Una bella feature che manca alla VCL imho e' un modo _semplice_ (una
property, per intendersi) di far girare la GUI in un proprio thread.
Saluti
Paolo Arosio

 priorità bassa.
Sulla priorita' da assegnare al thread staccato si puo' pronunciare solo
furiacdg (se e' un task importante non si dovra' bloccare solo perche'
l'utente trascina in giro la finestra per lo schermo <g>)
Saluti
Paolo Arosio

 property, per intendersi) di far girare la GUI in un proprio thread.
Vero.  Si sono inventati l'acrobazia del Synchronize che e'
veramente antipatica.


 l'utente trascina in giro la finestra per lo schermo <g>)
In realta', non credo che la priorita' dei task sia
un fattore importante in questo caso specifico e credo 
che, in generale, entri in gioco in misura sensibile 
solo per operazioni molto delicate, al limite del 
real-time.  
furiacdg vuole, se non ricordo male (ho la mail a casa),
mandare un'informazione via TCP/IP e aspettare la 
risposta.  In questo caso, Borland stessa, nella 
documentazione dei socket, consiglia di creare un
thread separato.  Anche perche' e' un'operazione
bloccante che non consente di effettuare un polling
su eventuali condizioni di uscita.


 while(isWorking) do Application.ProcessMessages;
Scusa furiacdg, ho contribuito a creare un po'
di confusione.  Cerco di riassumere, perche' mi
sembra di averti suggerito la soluzione sbagliata.
Grazie anche a Paolo che ha suggerito il while,
si puo' concludere che la soluzione giusta e'
l'unione delle due cose: creare il thread e 
usare il while.
Mi spiego:
La tua applicazione deve attendere la risposta
di una particolare funzione bloccante, senza 
bloccare, a sua volta, l'utilizzo dell'interfaccia
grafica.
Ora, utilizzare l'oggetto TEvent, seppure in un
thread separato, come ti ho suggerito, non 
risolve il problema, perche', comunque, nel 
thread primario dovrai usare un WaitFor 
sull'oggetto, riducendo si' il consumo di CPU,
ma congelando la GUI.
Se vuoi, invece, congelare solo la parte del tuo
processo che manda la richiesta su TCP/IP, 
allora devi creare un thread separato, farlo 
partire, metterti in attesa che una variabile
cambi valore (da true a false), crare un gestore
di messaggio personalizzato che imposti la 
variabile a false, far si' che il thread secondario,
a fine operazione, mandi il messaggio personalizzato
al form primario.
Se qualcuno ha una soluzione migliore...


Se qualcuno ha una soluzione migliore...
Ciao,
a "modo mio" ho risolto pilotando direttamente il winsock.
Quello che dovevo fare era:
- apri una connessione tcp
- scrivi una riga
- chiudi il socket
Il tutto in modo bloccante.
Ho usato TWinsockApi che fa il suo lavoro in modo lineare, come
l'avrei fatto in C.
Ciao e grazie a tutti
