* * * *

Privacy Policy

Blog italiano

Clicca qui se vuoi andare al blog italiano su Lazarus e il pascal.

Forum ufficiale

Se non siete riusciti a reperire l'informazione che cercavate nei nostri articoli o sul nostro forum vi consiglio di visitare il
Forum ufficiale di Lazarus in lingua inglese.

Lazarus 1.0

Trascinare un file nel programma
DB concetti fondamentali e ZeosLib
Recuperare codice HTML da pagina web
Mandare mail con Lazarus
Stabilire il sistema operativo
Esempio lista in pascal
File INI
Codice di attivazione
Realizzare programmi multilingua
Lavorare con le directory
Utilizzare Unità esterne
TTreeView
TTreeview e Menu
Generare controlli RUN-TIME
LazReport, PDF ed immagini
Intercettare tasti premuti
Ampliare Lazarus
Lazarus e la crittografia
System Tray con Lazarus
UIB: Unified Interbase
Il file: questo sconosciuto
Conferma di chiusura di un applicazione
Liste e puntatori
Overload di funzioni
Funzioni a parametri variabili
Proprietà
Conversione numerica
TImage su Form e Panel
Indy gestiore server FTP lato Client
PopUpMenu sotto Pulsante (TSpeedButton)
Direttiva $macro
Toolbar
Evidenziare voci TreeView
Visualizzare un file Html esterno
StatusBar - aggirare l'errore variabile duplicata
Da DataSource a Excel
Le permutazioni
Brute force
Indy 10 - Invio email con allegati
La gestione degli errori in Lazarus
Pascal Script
Linux + Zeos + Firebird
Dataset virtuale
Overload di operatori
Lavorare con file in formato JSON con Lazarus
Zeos ... dietro le quinte (prima parte)
Disporre le finestre in un blocco unico (come Delphi)
Aspetto retrò (Cmd Line)
Lazarus 1.0
Come interfacciare periferica twain
Ubuntu - aggiornare free pascal e lazarus
fpcup: installazioni parallele di lazarus e fpc
Free Pascal e Lazarus sul Raspberry Pi
Cifratura: breve guida all'uso dell'algoritmo BlowFish con lazarus e free pascal.
Creare un server multithread
guida all'installazione di fpc trunk da subversion in linux gentoo
Indice
DB concetti fondamentali e connessioni standard
Advanced Record Syntax
DB concetti fondamentali e DBGrid
DB concetti fondamentali e TDBEdit, TDBMemo e TDBText
Advanced Record Syntax: un esempio pratico
Superclasse form base per programmi gestionali (e non)
Superclasse form base per programmi gestionali (e non) #2 - log, exception call stack, application toolbox
Superclasse form base per programmi gestionali (e non) #3 - traduzione delle form
Superclasse form base per programmi gestionali (e non) #4 - wait animation
Un dialog per la connessione al database:TfmSimpleDbConnectionDialog
Installare lazarus su mac osx sierra
immagine docker per lavorare con lazarus e free pascal
TDD o Test-Driven Development
Benvenuto! Effettua l'accesso oppure registrati.
Novembre 11, 2025, 11:40:24 pm

Inserisci il nome utente, la password e la durata della sessione.

9 Visitatori, 0 Utenti

Autore Topic: Timer thread separato dal principale  (Letto 682 volte)

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3335
  • Karma: +12/-0
Timer thread separato dal principale
« il: Settembre 12, 2025, 08:40:25 am »
Buongiorno, mi pare se ne fosse parlato in passato, ma qualcuno sa dell'esistenza di un timer che fa girare la logica del suo codice in un thread separato così da non freezare il thread principale?!
Ieri è passato, domani è futuro, oggi è un dono...

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1662
  • Karma: +51/-0
  • Prima ascoltare, poi decidere
Re:Timer thread separato dal principale
« Risposta #1 il: Settembre 12, 2025, 08:59:34 am »
Ciao, da quello che sò io no.
Però puoi crearlo usando un TThread e chiamando la funzione specifica del sistema operativo che usi (per Windows l'API è " timesetevent").

Il problema di tutto ciò è che girando al di fuori del "Main Thread" le LCL non possono essere "toccate" in quanto non sono thread safe e non si possono generalmente usare al di fuori del thread principale.

Ciao
« Ultima modifica: Settembre 12, 2025, 09:02:43 am da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1662
  • Karma: +51/-0
  • Prima ascoltare, poi decidere
Re:Timer thread separato dal principale
« Risposta #2 il: Settembre 12, 2025, 09:54:26 am »
Ancora più banalmente puoi usare all'interno dell'evento del normale timer una funzione anonima:

Codice: [Seleziona]
procedure TForm1.OnTimer1((Sender: TObject);
begin
  TTask.Run(
           procedure
             begin
                 try
                    ////// QUI METTI QUELLO CHE VUOI VENGA ESEGUITO, qualunque cosa e viene eseguito in un pool di thread, non nel main thread
                    ////// L'esecuzione è asincrona rispetto al timer, quindi deve esserci un pò di attenzione all'enable e al disable (questo esempio è scorretto in quanto si potrebbero sovrapporre
                    ////// le esecuzioni se la stessa è più lente dell'intervallo del timer).
                 except on e:exception do
                     ;
                 end;
             end
         );
end;

EDIT: ovviamente vale lo stesso principio di esecuzione del multithreading, ossia le LCL devono essere gestite tramite un "synchronize" e non direttamente.
« Ultima modifica: Settembre 12, 2025, 10:00:51 am da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 3030
  • Karma: +21/-4
Re:Timer thread separato dal principale
« Risposta #3 il: Settembre 12, 2025, 10:16:57 am »
se il problema non è che devi usare il Timer ma di eseguire qualcosa non nel thread principale
puoi dare un'occhiata quì
https://www.freepascal.org/docs-html/rtl/classes/tthread.executeinthread.html

poi c'è anche questo
https://www.freepascal.org/docs-html/rtl/system/beginthread.html
Imagination is more important than knowledge (A.Einstein)

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3335
  • Karma: +12/-0
Re:Timer thread separato dal principale
« Risposta #4 il: Settembre 13, 2025, 09:55:28 am »
In pratica sto scrivendo un software basato in 3 parti

1. webserver json che incapsula tutta la logica dell'applicazione
2. client desktop per interagire con il webserver
3. app android per delle funzionalità specifiche che anche lei interagisce con il webserver

Il client desktop chiama le api per popolare i componenti, siccome è una soluzione per far lavorare contemporaneamente più persone, vorrei far aggiornare i contenuti in automatico se uno dei client cambia un dato devono reperirlo anche gli altri.

Quindi la mia idea era un timer sganciato dal thread principale che recupera i dati, se l'hash dei dati è diverso da quello che ho in memoria allora aggiorno i dati. Da qui la mia necessità. Ma se avete altri suggerimenti dite pure.
Ieri è passato, domani è futuro, oggi è un dono...

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 3030
  • Karma: +21/-4
Re:Timer thread separato dal principale
« Risposta #5 il: Settembre 15, 2025, 09:33:29 am »
credo che l'uso del timer possa andar bene
comunque per sia l'aggiornamento del client, visto che il codice in OnTimer gira nel thread principale, se è un processo "pesante" forse sarebbe meglio farlo fare in un thread separato
e, se lo metti nel thread separato, devi pensare anche ad un semaforo.

visto che lavorare nel main thread è più facile e visto anche che hai degli hash per gestire gli aggiornamenti
butto la un'idea:
1) nell'evento OnTimer, dal server remoto, leggi solamente gli hash e marchi le tabelle da aggiornare (operazione veloce che si dovrebbe risolvere con una unica chiamata per tutte le tabelle)
2) la procedura di aggiornamento parte, on demand, al verificarsi una certa azione, solo per le tabelle necessarie a quell'azione

esempio: caso nuovo DDT di trasporto
OnTimer tiene aggiornati gli hash in memoria ad intervalli, ad esempio, di 1 minuto
gli archivi che interessano in DDT di trasporto sono: archivio clienti, archivio articoli e archivio vettori
quando l'utente vuole fare un nuovo DDT, nel thread principale, potrebbe partire una procedura tipo:

Codice: [Seleziona]
procedure TMyApp.NuovoDDT;
begin
  AggiornaArchivi([Clienti, Articoli, Vettori]);
   [...]
end;

se gli hash non richiedono l'aggiornamento, l'utente non si accorge di nulla
se è necessario un aggiornamento, l'interfaccia mostrerebbe all'utente l'operazione in corso



nomorelogic


Edit:
si possono anche prevedere aggiornamenti totali sia all'avvio dell'app client, sia su richiesta del cliente
« Ultima modifica: Settembre 15, 2025, 09:39:18 am da nomorelogic »
Imagination is more important than knowledge (A.Einstein)

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3335
  • Karma: +12/-0
Re:Timer thread separato dal principale
« Risposta #6 il: Settembre 15, 2025, 02:51:18 pm »
Ma alla fine, ho deciso di provarci a scriverlo io, tanto può tornarmi utile anche in futuro.

Trovate il codice qui

https://github.com/XinYiMan/threadtimer

Nella sottocartella example c'è anche un esempio che dimostra come usarlo.

Fatemi sapere cosa ne pensate. Io al momento l'ho scritto e provato solo su windows. Nei prossimi giorni proverò anche su Mint. Se qualcuno ha modo di provarlo anche altrove e darmi un feedback mi farebbe un favore.

Grazie mille

PS: sono ben accetti suggerimenti per renderlo migliore. O se vedete dei bug segnalatemeli.
Ieri è passato, domani è futuro, oggi è un dono...

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1662
  • Karma: +51/-0
  • Prima ascoltare, poi decidere
Re:Timer thread separato dal principale
« Risposta #7 il: Settembre 15, 2025, 04:02:33 pm »
Uhla la, ma hai fatto una cosa professionale.

Allora, forse, per semplificare ho un idea ma devo testarla.

.....
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3335
  • Karma: +12/-0
Re:Timer thread separato dal principale
« Risposta #8 il: Settembre 16, 2025, 11:07:04 pm »
Timer aggiornato. Ho aggiunto la property State, che nei miei programmi uso per mantenere memorizzato l'hash della precedente esecuzione, così confrontandolo con quello nuovo capisco se devo eseguire OnAfterTimer e aggiornare i dati a video.
Inoltre ho testato il tutto anche su linux mint e sembra funzionare correttamente.
Ora lo posto anche sul forum internazionale, vediamo se qualcuno ha suggerimenti utili. DragoRosso aspetto comunque il tuo feedback dopo il tuo test.

Link: https://forum.lazarus.freepascal.org/index.php/topic,72289.0.html
« Ultima modifica: Settembre 16, 2025, 11:13:28 pm da xinyiman »
Ieri è passato, domani è futuro, oggi è un dono...

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1662
  • Karma: +51/-0
  • Prima ascoltare, poi decidere
Re:Timer thread separato dal principale
« Risposta #9 il: Settembre 23, 2025, 01:09:44 am »
Ciao, scusa il tempo passato ma gli impegni sono stati pesantucci.

Intanto ho visto il tuo componente, però l'ho trovato critico nella parte di scambio e immagazzinamento della variant.
Ovviamente è una mia fisima, probabilmente non riuscendo a trovare alcuna utilità in ciò (per i miei scopi ovviamente).

Il fatto di usare il doppio evento può essere interessante in effetti, ma non l'ho implementata in questa versione che allego per mancanza di tempo.

Il componente che ho costruito è analogo al TTimer di sistema, però con due funzionalità in più.

1) Droppando il componente in una form e assegnando un evento, tale evento viene eseguito nel thread principale in modalità asincrona, cioè l'evento continua ad essere chiamato continuamente ad ogni intervallo, indipendentemente dalla durata di esecuzione dell'evento stesso. Ciò è analogo al TTimer di sistema.
In questa modalità occorre stare attenti che l'elaborazione dell'evento non sia più lunga dell'intervallo: l'evento verrà chiamato comunque e quindi si potranno avere più esecuzioni sovrapposte.

2) Modificando la proprietà "Async" a false, l'evento verrà chiamato in modalità sincrona ossia il componente attende che l'evento termini e poi riparte con un successivo intervallo.La proprietà Async può essere modificata in un qualsiasi momento.

3) Creando il componente a RUNTIME con self (o qualsiasi altro componente istanziato) il comportamento è identico a quello di design time. Usando invece NIL l'evento verrà eseguito nel contesto del THREAD SEPARATO in modalità sincrona, in questo caso la proprietà ASync non ha alcun significato.

Cosa cambia rispetto a quanto hai fatto tu ? Essenzialmente viene usato un thread anonimo (o simile in FPC) e l'intervallo di tempo viene gestito tramite un evento.
Ciò dovrebbe migliorare l'efficienza e il carico del sistema rispetto allo sleep da te usato. Inoltre implementa la catena di notifica, che consente di gestire a livello di componete eventuali funzionalità.

Il componente è compatibile con Delphi e Lazarus, teoricamente su tutte le piattaforme. In Delphi si installa molto banalmente, in Lazarus si installa secondo quanto riportato dal file README.

Se non si vuole usarlo a design time (vista la peculiarità dell'esecuzione fuori thread principale) si può anche fare a meno di installarlo come componente e semplicemente usarlo a runtime inserendo nella USES l'unità.

Spero sia utile.

:) Ogni alba è un regalo, ogni tramonto è una conquista :)

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3335
  • Karma: +12/-0
Re:Timer thread separato dal principale
« Risposta #10 il: Settembre 23, 2025, 08:44:54 am »
Ciao DragoRosso. Molto interessante. Solo una precisazione, nel mio caso ho usato la sleep proprio perchè volevo con non partisse una seconda esecuzione senza che avesse finito la prima (io la uso per interrogare delle api). Proprio perchè a me serviva così. Però molto interessante il tuo approccio. Grazie mille
Ieri è passato, domani è futuro, oggi è un dono...

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1662
  • Karma: +51/-0
  • Prima ascoltare, poi decidere
Re:Timer thread separato dal principale
« Risposta #11 il: Settembre 23, 2025, 09:47:17 am »
Ciao DragoRosso. Molto interessante. Solo una precisazione, nel mio caso ho usato la sleep proprio perchè volevo con non partisse una seconda esecuzione senza che avesse finito la prima (io la uso per interrogare delle api). Proprio perchè a me serviva così. Però molto interessante il tuo approccio. Grazie mille
Nel thread separato funziona così. L'esecuzione è solo sincrona, quindi l'intervallo riparte solo dopo che l'evento è stato elaborato.

Ho inserito la possibilità di sync / async solo per allineare il componente al funzionamento standard (solo se l'evento viene eseguito nel Main Thread).
Ovviamente si possono modifcare facilmente sia i default che le funzionalità (ad esempio per aggiungere le tue features o per renderlo funzionale tramite flag piuttosto che in maniera automatica).

Per quanto riguarda lo sleep mi rifaccio alle mille discussioni avvenute sia qua che su altri siti e lo ritengo assolutamente inidoneo a fare ciò. Almeno nelle condizioni normali, senza hack.
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

 

Recenti

How To

Utenti
  • Utenti in totale: 829
  • Latest: Lorenzo
Stats
  • Post in totale: 20028
  • Topic in totale: 2412
  • Online Today: 20
  • Online Ever: 1080
  • (Novembre 10, 2025, 06:15:39 am)
Utenti Online
Users: 0
Guests: 9
Total: 9

Disclaimer:

Questo blog non rappresenta una testata giornalistica poiché viene aggiornato senza alcuna periodicità. Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n. 62/2001.