Lo so Synchronize
deve essere utilizzato nella procedura Execute
, ma dovrebbe essere utilizzato anche nei metodi Create
e Destroy
oppure è sicuro fare qualsiasi cosa io voglia?In quali metodi di thread dovrebbe essere utilizzato Synchronize?
risposta
È necessario utilizzare Synchronize()
quando il codice è in esecuzione al di fuori del contesto del thread principale (GUI) dell'applicazione. Quindi la risposta alla tua domanda dipende dal fatto che il costruttore e il distruttore siano chiamati da quel thread o meno.
Se non sei sicuro si può verificare che confrontando il risultato della funzione API di Windows GetCurrentThreadId()
con la variabile MainThreadID
- se eguagliare il codice viene eseguito nel contesto del thread principale.
I thread che hanno il set FreeOnTerminate
avranno il loro distruttore chiamato da un altro contesto di thread, quindi sarà necessario utilizzare Synchronize()
o Queue()
. Oppure si utilizza l'evento di terminazione già fornito dal VCL, credo che sia eseguito nel thread principale, ma si controlli la documentazione per i dettagli.
I know
Synchronize
must be used in the Execute procedure.
che è un po vago. È necessario utilizzare Synchronize
quando si dispone di codice che deve essere eseguito sul thread principale. Quindi la risposta alla necessità o meno di usare Synchronize
dipende in modo cruciale da ciò che il codice in esame effettivamente fa. La domanda che devi porci e che è una che solo tu puoi rispondere è che hai un codice che deve essere eseguito sul thread principale?
Come regola generale, sarebbe consigliabile evitare di dover chiamare il Synchronize
al di fuori del metodo Execute
. Se riesci a trovare un modo per evitare di farlo, sarebbe saggio. Ricorda che lo scenario ideale con i thread è che non hanno mai bisogno di bloccare con Synchronize
se possibile.
Si potrebbe anche voler considerare quale thread esegue il costruttore e il distruttore.
Il costruttore Create
viene eseguito nel thread che lo chiama. Non viene eseguito nel thread appena creato. Pertanto è improbabile che sia necessario utilizzare Synchronize
lì.
Il distruttore Destroy
viene eseguito nella discussione che lo chiama. In genere questo è il thread che chiama Free
sull'oggetto thread. E di solito questo sarebbe chiamato dallo stesso thread che originariamente ha creato il thread. L'eccezione comune a questo è una thread FreeOnTerminate
che chiama Free
dal thread.
Prima di tutto, non si desidera chiamare Synchronize()
inutilmente, perché ciò vanifica semplicemente lo scopo di utilizzare un thread. Quindi la decisione dovrebbe essere basata sul fatto che: (a) è possibile riscontrare condizioni di gara con dati condivisi. (b) utilizzerai il codice VCL che di solito deve essere eseguito sul thread principale.
È improbabile che sia necessario eseguire la sincronizzazione nel costruttore poiché le istanze TThread
vengono generalmente create già dal thread principale. (L'eccezione è se stai creando alcuni TThread
da un altro thread figlio.)
NOTA: non causerà alcun danno, però, perché Synchronize()
controlli già se siete sul thread principale e si chiama il metodo sincronizzato immediatamente se siete.
class procedure TThread.Synchronize(ASyncRec: PSynchronizeRecord; QueueEvent: Boolean = False);
var
SyncProc: TSyncProc;
SyncProcPtr: PSyncProc;
begin
if GetCurrentThreadID = MainThreadID then
ASyncRec.FMethod
Per quanto riguarda il distruttore ci sono 3 modalità di utilizzo:
- I
TThread
casi distrugge se stessa. - Un altro thread (probabilmente il thread principale) può
WaitFor
l'istanza da finire, quindi distruggerlo. - È possibile intercettare l'evento
OnTerminate
. Questo viene generato quando l'istanza è finita e tu potresti distruggerlo.
NOTA: L'evento OnTerminate
sarà già sincronizzato.
procedure TThread.DoTerminate;
begin
if Assigned(FOnTerminate) then Synchronize(CallOnTerminate);
end;
luce di quanto sopra, l'unica volta che potrebbe essere necessario per sincronizzare è se il filo si autodistrugge.
Tuttavia, ti consiglio di evitare di inserire il codice nel distruttore che potrebbe dover essere sincronizzato. Se hai bisogno di alcuni risultati di un calcolo dalla tua istanza di thread, OnTerminate
è il posto più appropriato per ottenere questo.
da aggiungere a quanto è stato detto in altre risposte ...
Non si può mai necessità da usare Synchronize
a tutti. Synchronize
può essere utile, tuttavia, nella seguente circostanza:
- Nel contesto del tuo thread è necessario eseguire il codice che tocca oggetti che hanno affinità con il thread principale.
- È necessario bloccare il thread finché il codice non è stato eseguito.
Anche in questo caso, ci sono altri modi per raggiungere lo stesso obiettivo, ma Synchronize
fornisce un modo conveniente per soddisfare queste due esigenze. Se hai bisogno solo di uno di questi due elementi, ci sono strategie migliori disponibili.
Sull'argomento n. 1, gli oggetti ovvi sono oggetti dell'interfaccia utente. Si tratta di oggetti che hanno affinità di thread con il thread principale semplicemente in virtù del fatto che il thread principale legge e scrive continuamente le proprietà di quegli oggetti (non ultimo perché ha bisogno di dipingerli sullo schermo, ecc.) E lo fa quindi a sua propria convenienza. Ciò significa che il thread non può accedere in modo sicuro a tali componenti con la garanzia che anche il thread principale non li accederà o li modificherà allo stesso tempo. Per prevenire la corruzione, il thread deve passare il lavoro al thread principale (dal momento che il thread principale può fare solo una cosa alla volta e non può, ovviamente, interferire con se stesso). Synchronize
posiziona semplicemente il lavoro sulla coda del thread principale e attende fino a quando il thread principale non si avvicina al completamento prima di tornare.
Questo arriva al punto # 2. Hai bisogno di (o, allo stesso modo, puoi permetterti di) aspettare fino a quando il thread principale termina il lavoro?Ci sono tre casi e due opzioni.
- Sì, è possibile o deve attendere. (
Synchronize
è una buona misura) - No, non puoi aspettare. (
Synchronize
non è una buona misura) - Non importa. (
Synchronize
è facile, quindi è una scelta sensata)
Se si sta semplicemente aggiornando una visualizzazione di stato che sarà presto sovrascritto in ogni caso e la vostra discussione ha problemi più pressanti, allora è probabilmente sensato solo inviare un messaggio al filo principale e continua a fare cose, per esempio. Se il tuo thread è solo in attesa di non fare nulla, soprattutto, e non vale la pena di codificare qualcosa di più sofisticato, allora Synchronize
va bene, e può essere sostituito con qualcosa di meglio se è necessario dettare così in futuro.
Come altri hanno già detto, dipende davvero da quello che stai facendo. La domanda più importante, secondo me, almeno concettualmente, è quella di risolvere quando è necessario preoccuparsi della concorrenza e quando non lo si fa. Ogni volta che si dispone di più thread che richiedono l'accesso a una singola risorsa, è necessario utilizzare una sorta di meccanismo per coordinare tale accesso per evitare che i thread si blocchino l'uno contro l'altro. Synchronize
è uno di quei metodi, ma non il minimo né l'ultimo di essi.
- 1. Node.js dovrebbe essere utilizzato per l'elaborazione intensiva?
- 2. Direct3D dovrebbe essere utilizzato su OpenGL in Windows?
- 3. Django dovrebbe essere utilizzato per siti grandi e complessi?
- 4. Can (dovrebbe) robolectric essere utilizzato per testare il filtro Intent
- 5. Ansible Copy vs Synchronize
- 6. Dovrebbe essere usato instancetype sui metodi alloc/new/init?
- 7. Quali metodi dovrebbero essere usati nella mia classe DDD factory?
- 8. La [tabella reloaddata] dovrebbe essere chiamata solo dal thread principale?
- 9. Delphi: un thread dovrebbe mai essere creato "non sospeso"?
- 10. Metodi Sonar non dovrebbe essere vuota al costruttore
- 11. FBSession: deve essere utilizzato solo da un singolo thread
- 12. Dovrebbe essere in un namespace?
- 13. metodi di chiamata in thread principale da altri thread
- 14. dovrebbe mai essere usato encodeURI?
- 15. Quali strumenti e metodi di test hanno utilizzato Corey Haines in GoGaRuCo 2011?
- 16. Quando deve essere utilizzato WS_EX_NOREDIRECTIONBITMAP?
- 17. Dove dovrebbe essere Android.mk?
- 18. synchronize database sqlite Android
- 19. dove dovrebbe essere "incluso" essere inserito in C++
- 20. dovrebbe essere chiuso Class.getResourceAstream?
- 21. CodeIgniter - Come controllare la sessione per essere utilizzato in ogni metodi
- 22. Cosa dovrebbe essere hadoop.tmp.dir?
- 23. L'importazione di caratteri jolly dovrebbe essere evitata?
- 24. In base a quale circostanza dovrebbe essere utilizzato INVISIBILE anziché GONE?
- 25. Dovrebbe essere std :: atomic volatile?
- 26. Prefisso per metodi di prova in Unità: "test" vs "dovrebbe"
- 27. dovrebbe ExecutorService essere statico e globale
- 28. Perché dovrebbe @@ class_variables essere evitato in Ruby?
- 29. Dovrebbe essere incluso Gemfile.lock in .gitignore?
- 30. Quali metodi implementano l'interfaccia buffer in Python?
Non è necessario utilizzare 'Synchronize()' se non è necessario sincronizzare nulla. Anche se si dispone di un thread di calcolo che produce risultati che si desidera visualizzare "quando pronto": non è necessario chiamare direttamente "Synchronize()". Se usi l'evento 'OnTerminate', Delphi lo sincronizza già per te. –
Come probabilmente si ottiene da altre risposte/commenti, il nome 'Synchronize()' viene in qualche modo scelto male. Dovrebbe davvero essere chiamato "ExecuteThisOnTheMainUIThread' perché questo è l'intero scopo: richiedere, all'interno del blocco Execute di un thread, che una parte di codice debba essere eseguita sul thread dell'interfaccia utente, consentendo così l'interazione con gli elementi dell'interfaccia utente. Tutto ciò che non ha bisogno di interagire con i controlli dell'interfaccia utente può essere eseguito all'interno del thread senza sincronizzazione con il thread dell'interfaccia utente. –
@ 500-InternalServerError: accetta la tua affermazione sul nome sbagliato. Sfortunatamente cadi nella stessa trappola con la tua ultima frase - dovrebbe essere qualcosa come "senza passare al thread dell'interfaccia utente", perché la corretta * sincronizzazione * (con tutti i thread, non solo il thread dell'interfaccia utente) potrebbe essere effettivamente necessaria. – mghie