2010-03-29 7 views
5

Domanda newbie: Ho una domanda di moduli. Ha un thread separato che effettua una chiamata ai servizi Web e quindi invia i risultati della chiamata al modulo principale.Devo liberare un oggetto Delphi auto-istanziato da una chiamata di servizi Web?

Nel mio thread, dopo X secondi sono passati (utilizzando un TTimer), mi chiama:

procedure TPollingThread.OnTimer(Sender: TObject); 
var 
SystemProbeValues : TCWProbeValues; 
begin 
SystemProbeValues := Remote.Run.GetSystemProbeValues; 
PostMessage(ParentHandle, WM_APIEVENT ,Integer(apiMultiCellStatus), Integer(SystemProbeValues)); 
end; 

I Remote.Run.GetSystemProbeValues ​​funzione ha il seguente prototipo:

function GetSystemProbeValues : TCWProbeValues; stdcall; 

E TCWProbeValues è una matrice dinamica di oggetti TCWProbeValue (che discendono tutti da TRemotable).

Nella mia forma principale, viene visualizzato il messaggio proprio bene e gettato il lParam torna a TCWProbeValues:

procedure TFrmCWMain.OnAPIEvent(var msg: TMessage); 
begin 
ProbeValues := TCWProbeValues(msg.LParam); 
end; 

La mia domanda è, dato che la matrice dinamica ei suoi oggetti sono stati creati dal sistema Delphi HTTORIO, chi è responsabile della loro liberazione? Delphi considerava la memoria riutilizzabile dopo il ritorno della mia funzione OnTimer? (E in tal caso, è pura fortuna che il mio gestore di messaggi principale possa effettivamente leggere la memoria a cui fa riferimento il LParam del messaggio?) O piuttosto, è mia responsabilità liberare l'oggetto auto-istanziato dalla richiesta HTTPRIO?

Mille grazie, per favore grida se quanto sopra ha bisogno di più dettagli/codice e lo aggiungerò ad esso!

Cheers, Duncan

risposta

4

TRemotable fornisce gestione della durata tramite la sua proprietà DataContext, in modo che il tempo di esecuzione SOAP libererà l'oggetto stesso. Finché esiste l'oggetto contesto dati, anche tutto ciò che esso alloca sarà. Se si desidera rivendicare la proprietà e la responsabilità di un oggetto, è sufficiente cancellare la proprietà DataContext. (Questo è probabilmente quello che si vorrà fare in questo caso perché il vostro messaggio di API-evento può ottenere gestito dopo l'evento SOAP è terminato.)


Un problema nel codice è che si sta passando una dinamica array tramite un messaggio postato. Quando la procedura OnTimer ritorna al chiamante, l'array dinamico a cui fa riferimento SystemProbeValues avrà il conteggio di riferimento decrementato. Se l'altro thread non ha ancora elaborato il messaggio (e probabilmente non lo ha ancora), allora l'array dinamico potrebbe già essere distrutto dal momento in cui lo fa andare in giro a elaborare quel messaggio.

Il modo semplice per cancellare il riferimento nel gestore di eventi del timer senza ridurre il conteggio dei riferimenti e quindi eseguire il contrario nel gestore di messaggi. Dopo si registra il messaggio, cancellare la variabile:

LParam(SystemProbeValues) := 0; 

Nel vostro gestore di messaggi, cancellare il vecchio valore della variabile globale ProbeValues e assegnare il nuovo valore in questo modo:

ProbeValues := nil; 
LParam(ProbeValues) := Msg.LParam; 

altro il problema che si annida nel tuo codice potrebbe essere l'uso di TTimer in un thread non VCL. Quella classe crea un handle di finestra da condividere tra tutte le istanze della classe.A meno che il thread del timer non sia l'unico thread del programma che utilizza TTimer, probabilmente si avranno problemi, sia con le funzioni in esecuzione nel thread sbagliato, sia con le funzioni che non funzionano affatto. Invece di TTimer, è possibile utilizzare SetTimer per creare manualmente un timer del sistema operativo oppure è possibile creare un waitable timer, che potrebbe essere più adatto per l'uso in un thread che non deve rimanere reattivo alle azioni dell'utente.