Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: washburn - Dicembre 31, 2020, 05:31:18 pm

Titolo: TCP Server e problema con Synchronize (TThreads)
Inserito da: washburn - Dicembre 31, 2020, 05:31:18 pm
Salve,

ho la necessità di "trasmettere" dati tra 2 Raspberry collegati in rete, 1 dei 2 (chiamato "PowerPi") è collegato ad un SDM120C che misura i consumi elettrici domestici, l'altro (chiamato "TankPi")  funge da controller per l'acquario che ho ed è equipaggiato con il display LCD 7" originale Raspberry.
Vorrei visualizzare i dati dei consumi su "TankPi" per cui ho pensato di aggiungere al software (Lazarus) che già funziona su "PowerPi" un TCP Server che risponda alle richieste di "TankPi" quando voglio visualizzare i dati dei consumi.
Ho trovato del codice di esempio su di un blog (http://pascalgeek.blogspot.com/2012/06/encryption-decryption-and-asynchronous.html (http://pascalgeek.blogspot.com/2012/06/encryption-decryption-and-asynchronous.html)) che fondamentalmente funziona ma ho fatto una piccola modifica al programmino originale "trasformando" il programma in un'applicazione "Form based", aggiungendo una ListBox a mo' di "log visuale" per vedere quando il client si connette al TCP server ed i dati che arrivano dal client.
Tutto funziona tranne quando, all'interno del Thread "TClientHandlerThread" (facendo riferimento al codice originale dell'autore), dopo la riga

Codice: [Seleziona]
Msg := FClientStream.ReadAnsiString;

ho aggiunto un:

Codice: [Seleziona]
logStr:= Msg;
Synchronize(@ScriviLog);

dove "ScriviLog":

Codice: [Seleziona]
Form1.ListBox1.Items.Add(logStr);
Sleep(1);
Application.ProcessMessages;

Quando il programma arriva su "Synchronize" si blocca un tempo infinito e non appare nulla sulla ListBox.
Non ho capito perchè...ho già usato i Threads e non ho mai verificato questo problema.
Da cosa può dipendere?
Grazie, saluti e Buon Anno !


Roberto
Titolo: Re:TCP Server e problema con Synchronize (TThreads)
Inserito da: bonmario - Dicembre 31, 2020, 07:35:32 pm
Ciao,
è passato tempo e non ricordo i dettagli, ma ricordo bene che se in una procedura sotto thread usavo "Application.ProcessMessages;", avevo dei problemi senza senso.
Prova a disattivare quella.

Se funziona, puoi aggiungere al progetto un timer (non sotto thread), che ogni tot tempo lancia la Application.ProcessMessages;

Ciao, Mario
Titolo: Re:TCP Server e problema con Synchronize (TThreads)
Inserito da: washburn - Dicembre 31, 2020, 07:48:55 pm
Ho provato a toglierlo ma il risultato è lo stesso  :'(
Titolo: Re:TCP Server e problema con Synchronize (TThreads)
Inserito da: bonmario - Dicembre 31, 2020, 08:05:19 pm
Prova a scrivere il log in un file di testo, e non nella listbox.
Se non va nemmeno così, magari c'è qualcosa che non va nel log che stai cercando di scrivere.

Ciao, Mario
Titolo: Re:TCP Server e problema con Synchronize (TThreads)
Inserito da: washburn - Gennaio 01, 2021, 03:38:30 pm
Sul file di testo funziona ma poi ho qualche problema a reinviare il messaggio ricevuto al client come "prova" di ricezione, in una sorta di "echo".
Ho scaricato e provato i componenti "LNet" e vedo che funzionano molto bene e sono abbastanza facili da usare quindi utilizzerò quelli.
Grazie per il supporto e...buon anno !



Roberto
Titolo: Re:TCP Server e problema con Synchronize (TThreads)
Inserito da: bonmario - Gennaio 01, 2021, 05:15:59 pm
Per caso, il log che avresti voluto emettere nella ListBox, era lungo?
Se è così, magari bastava solo mettere un BeginUpdate prima ed un EndUpdate dopo

Ciao, Mario
Titolo: Re:TCP Server e problema con Synchronize (TThreads)
Inserito da: washburn - Gennaio 01, 2021, 07:01:14 pm
No, era una semplice stringa di 10 caratteri.


Roberto
Titolo: Re:TCP Server e problema con Synchronize (TThreads)
Inserito da: xinyiman - Gennaio 02, 2021, 02:58:02 pm
Supponendo che la form su cui si trova la listbox si chiama FrmMain dichiara una variabile di tipo stringa e la chiami miastringa. Poi sempre li crei una procedura (sempre pubblica) che prende il valore di mia stringa e la aggiunge alla listbox. Poi nel codice del thread usi un codice simile a quello che segue quando vuoi comunicare il messaggio (lo sostituisci a hello world). Ricordati che nella sezione public della form FrmMain deve essere dichiarata anche

CriticalSectionController : TRTLCriticalSection;

Nella formcreate usi questo codice

InitCriticalSection(CriticalSectionController);

e nella formdestroy usi

DoneCriticalsection(CriticalSectionController);

Codice: [Seleziona]
     EnterCriticalsection(FrmMain.CriticalSectionController);

     FrmMain.miastringa  := 'hello world';
     Synchronize(@FrmMain.ControllerAction);

     LeaveCriticalsection(FrmMain.CriticalSectionController);