* * * *

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.
Aprile 16, 2026, 10:29:02 am

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

316 Visitatori, 0 Utenti

Autore Topic: eseguire una procedura di caricamento dati in background  (Letto 4142 volte)

petrusic

  • Hero Member
  • *****
  • Post: 703
  • Karma: +0/-0
eseguire una procedura di caricamento dati in background
« il: Marzo 17, 2026, 10:05:30 am »
Lo so, non sono stato più prtesente nel Forum per tanto tempo, ma sono stato assorbito dal mio solito nuovo programma che porto avanti molto lentamente ed ho trascurato molte cose, fra cui quello che mi ero ripromesso di fare, cioè partecipare in maniera diversa e più frequentemente alle discussioni aperte.

Mi trovo davanti ad una necessità, quella di attivare, all'avvio di una Form, basilare per l'inserimento dati, senza fare pesare all'utente l'attesa dovuta ai tempi di caricamento di dati dal DataBase.

Visto che i dati da caricare in memoria non occorrono per la digitazione all'interno del primo controllo attivo della Form, vorrei eseguire detto caricamento in maniera trasparente e sovrapposta all'attività di digitazione dell'utente (in background).

Inizialmente, avevo inserito detto caricamento nella FormCreate, ma dovevo aspettare il termine del caricamento per potere vedere apparire la Form chiamatra.

Poi ho pensato di sfruttare l'evento OnShow ed ho spostato le istruzioni all'interno della FormShow, ma anche così facendo il cursore di Pronto per la digitazione non compare se non dopo il completamento del caricamento dati.

A questo punto vorrei tentare di spostare quelle istruzioni dentro una routine procedurale da fare eseguire in background, ma non ho idea di come ottenere l'effetto desiderato.

Insomma, ho ancora bisogno del vostro preziozo aiuto.  :D
ciao ciao

xinyiman

  • Administrator
  • Hero Member
  • *****
  • Post: 3351
  • Karma: +12/-0
Re:eseguire una procedura di caricamento dati in background
« Risposta #1 il: Marzo 17, 2026, 11:48:56 am »
Buongiorno, nessun problema, ognuno partecipa al forum come può. Per il tuo problema penso che la cosa più semplice sia mettere il caricamento dati in un timer.
Tu nell'oncreate metti l'avvio del timer dopo 2/3 secondi e così la form si vede.
Ieri è passato, domani è futuro, oggi è un dono...

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1737
  • Karma: +53/-0
  • Prima ascoltare, poi decidere
Re:eseguire una procedura di caricamento dati in background
« Risposta #2 il: Marzo 17, 2026, 11:59:58 am »
Ciao e benritornato.
Devo intanto darti alcune delucidazioni perchè tu apprenda dei particolari tecnologici, senza i quali qualunque soluzione pensata non potrà mai avere un buon esito.

Primo: perchè si attende (o meglio l'operatore attende), ovvero perchè il software sembra fermarsi ?

Ciò accade perchè tutte le attività di visualizzazion sono e devono essere serializzate, quindi ad esempio quando carichi i dati in un form questi vengono caricati (e devono essere caricati) senza intervento di "thread" diretti. In pratica questa operazione DEVE (e viene) eseguita all'interno del THREAD PRINCIPALE (Main Thread) che esegue tutte le operazioni sui controlli grafici (la UI) in maniera serializzata.

Quando scorri un database e riempi una griglia (TStringGrid a esempio), solo ed esclusivamente il "Main Thread" potrà disegnare e riepmipre la griglia.
E quando il "Main Thread" è troppo occupato a riempire una griglia da un database ad esempio ovviamente non si occupa di tutto il resto (come mouse, tastiera e altri controlli grafici) ... da cui il blocco apparente dell'interfaccia.

Tutto ciò dipende dalla potenza di elaborazione che hai a disposizione ...

Tutto ciò che ha a che fare con gli Eventi a design time o run time (in generale) e con le LCL (le librerie grafiche di Lazarus) usano il Main Thread e quindi vengono eseguite singolarmente una dietro l'altra, mai in parallelo.

Se per caricare una griglia ci si impiega dieci secondi, per dieci secondi l'interfaccia verrà congelata. Non ci sono alternative a ciò (a meno che non si voglia giocare al lotto e crearsi problemi futuribili poi difficilmente tracciabili e identificabili).

Ciò che chiedi quindi a prima vista non è così facilmente eseguibile.

Quando si ha a che fare con i database, generalmente si usano le "copie in memoria" (cioè una query già eseguita senza aggacnio con la parte grafica) per la visualizzazione.

In questo caso ciò che puoi fare banalmente è disattivare il controllo grafico (la tua StringGrid ad esempio con la sua proprietà Enabled := false), eseguire la query agganciata alla griglia e riattivare il controllo grafico una volta terminata la query.

La Query la puoi eseguire in un Thread separato dal principale (quindi non nel OnSHow, OnCreate o altro) e quindi tutto il tempo di esecuzione della query non bloccherà l'interfaccia (AMMESSO CHE I CONTROLLI GRAFICI AGGANCIATI ALLA QUERY SIANO DISATTIVATI).

Se il contenuto della StringGrid viene riempita a codice, allora tutto è più complesso e dipende dalla tecnica usata per la sua visualizzazione (o riempimento).

Ciò è indifferente al linguaggio usato, sia esso Pascal, C#, Rust o altro. I concetti sono esattamente gli stessi in tutti i linguaggi.
Poi ci sono gli ausili che i linguaggi o le RTL del linguaggi ti forniscono per aiuarti in ciò, e quindi il linguaggio per avere più o meno impatto sull'uso.

Puoi fare un semplice test disattivando i controlli grafici (una tua StringGrid) durante l'esecuzione della Query corrispondente per poi riattivarla alla fine e vedere che impatto ha sulla tua applicazione.

Intanto questo e dimmi se hai compreso il tutto e come è andato il test. Poi si passerà alle cose più complesse se non fosse soddisfacente il risultato.
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 3065
  • Karma: +23/-4
Re:eseguire una procedura di caricamento dati in background
« Risposta #3 il: Marzo 17, 2026, 12:15:33 pm »
A questo punto vorrei tentare di spostare quelle istruzioni dentro una routine procedurale da fare eseguire in background, ma non ho idea di come ottenere l'effetto desiderato.

potresti provare a vedere qualcosa del genere

il sorgente è scritto a mano (non l'ho provato) e prevede il passaggio di procedura anonima
che versione di FPC usi?


in alternativa devi usare un TThread

Codice: [Seleziona]
procedure TForm1.RunQuery; // metodo che esegue query pesante
begin
  // SELECT * FROM QUALCHE_TABELLA
end;

// in un bottone, nel button click o in OnCreate della Form1:
TThread.CreateAnonymousThread(
  procedure
  begin
    RunQuery;
  end
).Start;
Imagination is more important than knowledge (A.Einstein)

petrusic

  • Hero Member
  • *****
  • Post: 703
  • Karma: +0/-0
Re:eseguire una procedura di caricamento dati in background
« Risposta #4 il: Marzo 17, 2026, 12:40:05 pm »
che versione di FPC usi?
Codice: [Seleziona]
Effettivamente non è recente:
[quote]
Il mio Lazarus è la versione 3.8 - 20.lug.2025, mentre lka versione FPC è la 3.2.2 [/quote]
ciao ciao

petrusic

  • Hero Member
  • *****
  • Post: 703
  • Karma: +0/-0
Re:eseguire una procedura di caricamento dati in background
« Risposta #5 il: Marzo 17, 2026, 12:43:11 pm »
. . .
Quando si ha a che fare con i database, generalmente si usano le "copie in memoria" (cioè una query già eseguita senza aggacnio con la parte grafica) per la visualizzazione.

In questo caso ciò che puoi fare banalmente è disattivare il controllo grafico (la tua StringGrid ad esempio con la sua proprietà Enabled := false), eseguire la query agganciata alla griglia e riattivare il controllo grafico una volta terminata la query.

La Query la puoi eseguire in un Thread separato dal principale (quindi non nel OnSHow, OnCreate o altro) e quindi tutto il tempo di esecuzione della query non bloccherà l'interfaccia (AMMESSO CHE I CONTROLLI GRAFICI AGGANCIATI ALLA QUERY SIANO DISATTIVATI).
Se il contenuto della StringGrid viene riempita a codice, allora tutto è più complesso e dipende dalla tecnica usata per la sua visualizzazione (o riempimento).
. . .

Nel mio post d'apertura ho  fatto cenno ad un caricamento in memoria, non in controllo grafico come una griglia.
Ho capito che FormCreate e FormShow NON mi permettono di realizzare quello che mi propongo e per questo ho pensato ad una routine , routine che, però, devo richiamare da qualche parte. Attualmente la richiamo dentro la FormShow.

Comunque, proverò la procedura anonima che m i ha suggerito nomorelogic.
ciao ciao

nomorelogic

  • Global Moderator
  • Hero Member
  • *****
  • Post: 3065
  • Karma: +23/-4
Re:eseguire una procedura di caricamento dati in background
« Risposta #6 il: Marzo 17, 2026, 04:02:48 pm »
che versione di FPC usi?
Codice: [Seleziona]
Effettivamente non è recente:
[quote]
Il mio Lazarus è la versione 3.8 - 20.lug.2025, mentre lka versione FPC è la 3.2.2 [/quote]

lazarus è vecchiottello ma fpc dovrebbe andar bene
Imagination is more important than knowledge (A.Einstein)

petrusic

  • Hero Member
  • *****
  • Post: 703
  • Karma: +0/-0
Re:eseguire una procedura di caricamento dati in background
« Risposta #7 il: Marzo 17, 2026, 04:13:33 pm »
potresti provare a vedere qualcosa del genere

il sorgente è scritto a mano (non l'ho provato) e prevede il passaggio di procedura anonima

in alternativa devi usare un TThread
Codice: [Seleziona]
procedure TForm1.RunQuery; // metodo che esegue query pesante
begin
  // SELECT * FROM QUALCHE_TABELLA
end;

// in un bottone, nel button click o in OnCreate della Form1:
TThread.CreateAnonymousThread(
  procedure
  begin
    RunQuery;
  end
).Start;

Ho cercato di approfondire la conoscenza della tecnica TThread ed ho trovato Qui un argomento che sembrava potesse aiutarmi, ma alla fine mi sono convinto che non è la strada che cercavo, infatti ho capito che creare TThread anonimo corrisponderebbe a scrivere un programmino che può partire in parallelo su un altro core del pc e che svolge il suo lavoro in maniera assolutamente autonoma. Alla fine del suo lavoro, occorrendo, valorizzerebbe le variabili al suo interno, variabili che restano sue, quindi non accessibili dall'esterno.

Ma ciò non è ciò mi serve. Io devo raggiungere uno scopo esettamente opposto, prelevando e usando proprio le variabili ricavate dalla procedura TThread.

Penso perciò che opterò per lanciare un messaggio d'Attesa che eliminerò alla fine della memorizzazione dei miei dati prelevati dal DB e continuerò a quel pun to col mostrare la mia Form di inserimento movimenti.

Grazie per i suggerimenti. Ho conosciuto un altro strumento.
ciao ciao

DragoRosso

  • Scrittore
  • Hero Member
  • *****
  • Post: 1737
  • Karma: +53/-0
  • Prima ascoltare, poi decidere
Re:eseguire una procedura di caricamento dati in background
« Risposta #8 il: Marzo 17, 2026, 04:49:25 pm »
infatti ho capito che creare TThread anonimo corrisponderebbe a scrivere un programmino che può partire in parallelo su un altro core del pc e che svolge il suo lavoro in maniera assolutamente autonoma. Alla fine del suo lavoro, occorrendo, valorizzerebbe le variabili al suo interno, variabili che restano sue, quindi non accessibili dall'esterno.
Ma ciò non è ciò mi serve. Io devo raggiungere uno scopo esettamente opposto, prelevando e usando proprio le variabili ricavate dalla procedura TThread.

Funziona così solo se lo programmi così. Il thread può agire banalmente su oggetti globali o pubbliche di altre entità (classi, interfacce, record, etc ...), in modo tale che il risultato rimanga pubblico e/o globale (o all'interno della classe / record, genericamente nell'oggetto di appartenenza).
L'attenzione che devi porre è CHE NON SI DEVE MAI ACCEDERE ALLA STESSA RISORSA DA PIU' THREAD CONTEMPORANEAMENTE (CIOE' NON SINCRONIZZATI).

Significa che la tua Query può essere globale o una proprietà/procedura/funzione pubblica della form o del DataModule e dal tuo Thread (Anonimo o no) ci puoi accedere ed eseguirla.

Durante l'esecuzione del thread non DEVI IN ALCUN MODO CERCARE DI ACCEDERE ALLA STESSA RISORSA (QUERY / FUNZIONE / PROCEDURA / PROPRIETA' / ETC ...).

Inoltre sarebbe utile che il Thread comunicasse la fine elaborazione settando un evento / messaggio o ponendo a 1 una variabile globale (tramite Interlocked ad esempio).
Ricordiamoci magari anche la gestione degli errori (altra variabile globale) visto che un Thread Anonimo sarebbe utile (scusate la ripetizione) non generasse una eccezione.

N.B.: e ovviamente il tuo thread NON DEVE ACCEDERE A NULLA DI GRAFICO (OSSIA A NULLA DELLE LCL).

P.S.: il fatto che un thread (software) giri su un altro CORE/THREAD (HARDWARE) è ininfluente, lo scopo è non usare / usare il meno possibile il Main Thread (che è software).
« Ultima modifica: Marzo 17, 2026, 04:53:09 pm da DragoRosso »
:) Ogni alba è un regalo, ogni tramonto è una conquista :)

 

Recenti

How To

Utenti
Stats
  • Post in totale: 20264
  • Topic in totale: 2441
  • Online Today: 339
  • Online Ever: 1080
  • (Novembre 10, 2025, 06:15:39 am)
Utenti Online
Users: 0
Guests: 316
Total: 316

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.