Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: guest1752 - Novembre 13, 2018, 08:56:08 am

Titolo: Thread e piccolo dubbio
Inserito da: guest1752 - Novembre 13, 2018, 08:56:08 am
Ciao a tutti:

ho scritto questo piccolo thread per la mia applicazione; serve per far lampeggiare una label (visibile/ invisibile):
Codice: [Seleziona]
  TBlinker = class(TThread)
  private
    ftLabel: TLabel;
    procedure setComponentLabel(AValue: TLabel);

  protected
     procedure Execute; override;
  public
     ctrVar: Boolean;
     constructor Create(CreateSuspended: boolean);

     property setLabel: TLabel read ftLabel write setComponentLabel;
     procedure reverseBlink;
  end;   

procedure TBlinker.setComponentLabel(AValue: TLabel);
begin
  if ftLabel=AValue then Exit;
  ftLabel:=AValue;
end;

procedure TBlinker.reverseBlink;
begin
  ftLabel.Visible:= not ftLabel.Visible;
end;

procedure TBlinker.Execute;
var
  i: Integer;
begin
  while not Terminated and (ctrVar = true) do
  begin
    Synchronize(@reverseBlink);
    Sleep(500);
  end;
end;

constructor TBlinker.Create(CreateSuspended: boolean);
begin
  FreeOnTerminate := True;

  inherited Create(CreateSuspended);
    ctrVar:=true;

end; 

In seguito ho dichiarato come globale un bel puntatore alla TBlinker:
Codice: [Seleziona]
    pnt_blinker: ^TBlinker;    

Ho dichiarato un funzione per la creazione del thread:
Codice: [Seleziona]
function TFormMain.createBlinker: Boolean;
var
  bp: TBlinker;
begin
  try
    bp := TBlinker.Create(true);
    pnt_blinker := @bp;
    bp.setComponentLabel(Label1);
    bp.FreeOnTerminate:= true;
    bp.Start;
  finally
  end;
end; 

In un altro bottone avrei voluto stoppare il thread utilizzando pnt_blinker, ma il thread parte e vedo lampeggiare la scritta ma
se lo vado a sospendere per esempio con 
Codice: [Seleziona]
TBlinker(pnt_blinker).ctrVar:=false; 
, cioè facendo terminare il thread con la
variabile di controllo del ciclo, ma anche con i metodi terminate del thread, il thread non si ferma.


Dove sto sbagliando?









Titolo: Re:Thread e piccolo dubbio
Inserito da: xinyiman - Novembre 13, 2018, 09:04:05 am
L'ideale sarebbe che postassi un piccolo esempio con il problema annesso, così noi lo compiliamo e lo analizziamo.
Titolo: Re:Thread e piccolo dubbio
Inserito da: guest1752 - Novembre 13, 2018, 09:10:58 am
ok ci provo, tuttavia fa parte di un progetto abbastanza grande e non potrei postarlo, comunque proprio ora ho provato a non utilizzare il pnt_blinker per accedere alla "bp: TBlinker" dichiarato nella proc createBlinker, ma ho messo bp in public e funziona.
Dopo faccio un progettino a parte e lo posto.
Titolo: Re:Thread e piccolo dubbio
Inserito da: guest1752 - Novembre 13, 2018, 11:43:22 am
Ecco, ho creato un nuovo progetto ma si comporta in maniera simile; che cavolata mi sfugge?
Titolo: Re:Thread e piccolo dubbio
Inserito da: xinyiman - Novembre 13, 2018, 02:10:08 pm
Come prima cosa devi aggiungere in

Progetto -> Opzioni progetto -> Varie

e in Opzioni Personalizzate inseriamo la seguente stringa: -dUseCThreads

Questo per farlo funzionare anche fuori da ambienti windows, quindi per linux o mac, altrimenti trovi un eccezzione.

Poi guarda il sorgente da me modificato, vedrai che ho cambiato la logica della lettura di quella variabile, non la imposto dal main, ma dal processo separato vado a leggerne il contenuto. Così a me funziona.

Fammi sapere
Titolo: Re:Thread e piccolo dubbio
Inserito da: guest1752 - Novembre 13, 2018, 03:43:49 pm
dunque si io ho usato nel sorgente del progetto   
Codice: [Seleziona]
{$ifdef unix}
  cthreads,
  cmem,
{$endif}   
infatti su raspbian dava errore.

Si funziona; la mia intenzione era in pratica creare una variabile locale della funzione per poi assegnargli un puntatore da gestire ovunque, ma alla fine del thread nel finally, viene eliminato e quindi ho un errore.
In c avevo avuto un problema simile, cioè ho creato una funzione che mi tornava un puntatore a una struct che al suo interno aveva puntatori a funzione, quindi con il malloc e il sizeof creava quello a tutti gli effetti è un oggetto, ma se lanciavo il programma da debug del codeblock nella fattispecie funzionava in release no. Ho settato la funzione come static e dopo mi tornava correttamente l'oggetto creato dalla funzione. La gestione della memoria in lazarus è differente devo ripassare per bene.
Grazie ancora e per informazione una lettura interessante è https://www.codementor.io/michaelsafyan/object-oriented-programming-in-c-du1081gw2 (https://www.codementor.io/michaelsafyan/object-oriented-programming-in-c-du1081gw2)



Titolo: Re:Thread e piccolo dubbio
Inserito da: xinyiman - Novembre 13, 2018, 04:30:15 pm
Guarda, concettualmente è molto semplice, per non aver problemi parti dal presupposto di leggere e scrivere dal thread separato e non da quello principale. Risolvi tutti i problemi