Newsgroup: it.comp.lang.delphi
Titolo: Thread, Indy e VCL

Ciao a tutti,
sto lavorando con Indy 10 con oggetti
tipo Server e Client TCP.
L'evento EXECUTE del server TCP è gestito
autonomamente da Indy come un thread,
nella mia applicazione ne ho 5.
Alla fine di ognuno di questi Thread, devo cambiare
una proprietà di altrettanti Panel nella Mainform (in particolare
devo cambiarne il colore);
so che i Panel non sono Thread-Safe,
ma non so come fare a sincronizzarli
all'interno dell'Execute del Thread del Server Indy.
Mi potete aiutare?
Grazie in anticipo, Fabrizio.

all'interno dell'Execute del Thread del Server Indy.
Una soluzione può essere quella di usare dei PostMessage() o SendMessage()
V. 

Mi potete aiutare?
La via più sicura (fidati) è usare i messaggi di Windows, sia per la
comunicazione tra thread che tra thread e thread primario (quello che
gestisce la GUI per intenderci). Alla fine dell'elaborazione di ogni
thread, lancia semplicemente un messaggio (usa ovviamente PostMessage,
non SendMessage) alla finestra principale.

 non SendMessage) alla finestra principale.
Perchè ovviamente, Andrea?
Non potrebbe aver bisogno di attendere il termine dell'elaborazione della
procedura?
Te lo chiedo perchè personalmente in alcuni casi ho optato per l'uso di
SendMessage(), ritieni sia una scelta azzardata anche se coperti da
opportuni Try?
Ciao
V

opportuni Try?
Non riesco a contemplare un singolo caso in cui SendMessage() sia più
opportuna di PostMessage() in un contesto multithread. Trattandosi di
thread, la modalità asincrona è quella da preferire.

Valter non ha senso usare SendMessage da un thread: cio' significa far 
eseguire l'evento relativo in sincronismo al thread ed in "contemporanea" 
all'esecuzione del thread principale o degli altri thread.
Faccio un esempio: supponiamo che dal tuo thread si debbano modificare 3 
variabili che sono utlilizzate dal principale per eseguire un calcolo.
Se il thread tramite il SendMessage le sta modificando e 
"contemporaneamente" il principale le legge, puo' succedere che alcune siano 
state "rinnovate" e le altre no ... con la conseguenza che puoi imagginare.
ciao giorgio 

Grazie a tutti.
L'unico problema è che non ho trovato molto sull'utilizzo
della PostMessage; come posso fare?
Esistono degli esempi da qualche parte in rete
che mi aiutino a partire?
Io devo solo scrivere Caption o cambiare Colori
in Label e Panel di un form.
Grazie ancora, Fabrizio

 variabili che sono utlilizzate dal principale per eseguire un calcolo.
Casi come questi si risolvono con la sincronizzazione tra thread. Il
problema è che si vuol proprio evitare la sincronizzazione esplicita tra
thread (che almeno una possibilità di deadlock, per quanto il codice sia
scritto bene, la mettono in gioco). Con PostMessage si evita del tutto
anche solo di contemplare la possibilità di un deadlock. Certo, lo
svantaggio è che esiste la remotissima ("molto remotissima"...)
possibilità che il messaggio non arrivi.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 in Label e Panel di un form.
Dichiara un tuo messaggio di notifica (basta incrementare di una costante
WM_USER); crea i tuoi thread secondari passando al costruttore l'handle
della form che dovrà aggiornare i componenti grafici; fai in modo che al
termine dell'execute dei tuoi thread (o in qualsiasi altro momento ritieni
giusto), venga inviato il tuo messaggio custom alla form di cui sopra. La
form avrà, presumibilmente, un componente di tipo ApplicationEvents, al
cui evento OnMessage aggancerai il codice di elaborazione dei messaggi
custom (se ne arrivano). L'OnMessage, essendo un evento, funziona solo se
hai usato PostMessage (come consigliato) e non SendMessage.



però supponiamo che il thread non interagisca con la finestra principale se 
non per cambiare la caption di alcune TLabel o scrivere in una TMemo e che 
io voglia essere certo che tali cambiamenti avvengano serialmente e nel 
medesimo istante in cui invio i messaggi...
se utilizzo SendMessage() il thread resterà in attesa del completamento 
dell'operazione, con PostMessage() i messaggi si accumuleranno in coda e se 
le chiamate sono a breve distanza l'una dall'altra potrei ottenere una 
visualizzazione "fuori sincronia"...
non so, non sono così convinto che PostMessage() sia da preferire 
dogmaticamente a SendMessage()...io credo che dipenda da quanto si vuole 
ottenere ( ovviamente curando i dettagli di un possibile "non ritorno" )
ciao
V


Dichiara una costante:
Const
  WM_AGGIORNAPANEL = WM_USER + 1;
Nella sezione Private della form che deve ricevere il messaggio:
Private
  PROCEDURE WMAGGIORNAPANEL(VAR Msg : TMessage); message 
WM_AGGIORNAPANEL;
PROCEDURE Tform1.AMADDTOTREELIST(VAR Msg : TMessage);
Begin
  Panel1.Color:= clRed;
End;
Usa questo per spedire il messaggio:
PostMessage(Handle, WM_AGGIORNAPANEL, 0,0);
Handle e l'Handle della Form che deve ricevere il messaggio.
Ciao
--- posted by geoForum on 
http://www.delphiedintorni.it

 medesimo istante in cui invio i messaggi...
Se vuoi che i cambiamenti avvengano serialmente, non ti conviene usare una
struttura multithread (e non riesco ad immaginare un singolo caso concreto
in cui possa essere conveniente una serializzazione di questo tipo). In un
contesto MT, più si è svincolati dalla serializzazione, meglio è.


 medesimo istante in cui invio i messaggi...
Se vuoi che i cambiamenti avvengano serialmente, non ti conviene usare una
struttura multithread (e non riesco ad immaginare un singolo caso concreto
in cui possa essere conveniente una serializzazione di questo tipo). In un
contesto MT, più si è svincolati dalla serializzazione, meglio è.
Aggiungo che, anche nel caso si desideri serializzazione, è bene che
questa logica stateful sia comunque mantenuta dal thread primario e non
comandata esplicitamente dai thread.


 visualizzazione "fuori sincronia"...
Se hai fenomeni di lento aggiornamento grafico, ed e' questo il motivo che 
ti preoccupa a quanto ho capito,
nel gestore dell'evento che mandi in esecuzione tramite il Postmessage 
mettici un "Componente.repaint" relativo al componente/i che vai a 
modificare.
Ciao Giorgio