zwracanie wartości funkcji z osobnego wątku

0

Piszę aplikację która w tle co jakiś czas pobierać będzie informacje z serwera i wyświetlać je w TLabel. Musi to dziać się jednak w osobnym wątku który nie przeszkadza aplikacji (w tle).

Mam coś takiego:

unit MainFrmU;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
  IdTCPClient, IdHTTP, IdMultipartFormData;

type
  TMainFrm = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
  TConnect = class(TThread)
  private
    {}
  protected
    procedure Execute; override;
  public
    function Connect(url, param: string): string;
  end;

var
  MainFrm: TMainFrm;

implementation

{$R *.dfm}

procedure TConnect.Execute;
begin
  FreeOnTerminate := true;
end;

function TConnect.Connect(url, param: string): string;
begin
{
Ta funkcja łączy sie z serwerem i zwraca otrzymane informacje
}
end;

end.

ale nie mam pojęcia jak z klasy TMainFrm wywołać funkcję CONNECT (wątek TConnect) i w głównej klasie otrzymać wynik tej funkcji. Teorytycznie coś takiego:

procedure TMainFrm.Button2Click(Sender: TObject);
var
  con: TConnect;
begin
  con := TConnect.create(nil);
  label1.caption := con.Connect('http://www.strona.pl', 'parametry dla serwera');
end;

Niby coś tam udało mi się zrobić aby działało ale nie wyglądało to na wielowątkowość bo blokowało formę i w trakcie przesuwania okienka nic się nie działo do czasu puszczenia kursora. Jak to powinno wyglądać aby działało "tak na prawdę w tle"?

0

tu masz wszystko: Rozdział 8
szczegolna uwage zwroc na "synchronize".

0

Przecież twój kod dokładniej jego większość (dosłownie oprócz FreeOnTerminate := true;) nie wykonuje się w wątku dlatego "blokuje formę" w wątku wykonuje się kod zawarty w Execute.

0

Możesz też skorzystać z biblioteki OmniThreadLibrary.

Link: http://www.thedelphigeek.com/2011/10/multithreading-made-simpleadditional.html
Jest tam prezentacja i kod źródłowy, są też odpowiednie metody jak zwracać wartości z wątków.

0

Ale może tak jak zauważył kAzek, niech najpierw poczyta podstawy o wątkach.

0

Skoro jedyne co odbywa się jako oddzielny proces to procedura execute to w jaki sposób mogę zrobić aby zwróciła ona jakąś wartość?

0

Jako oddzielne co? :O

0

Miałem na myśli wątek a nie proces. Moja pomyłka. Generalnie chodzi mi o to aby była to funkcja która zwraca wartość a nie żeby procedura execute wyświetlała wynik w labelu.

0

To można by zrobić chyba tylko przez: TThread.OnTerminate - poczytaj o tym, może to spełni twoje oczekwania.
Ale to co podałeś w pierwszym poście, to jak najbardziej można zrobić w metodzie Execute - zwracanie wyniku przez metodę: TThread.Synchronize.

1

znawcą wątków nie jestem, więc krzyczcie jesli tak nie wolno:

wątek:

type
  TCallback =procedure(Odpowiedz:String) of object;

type
  TWatek = class(TThread)
  private
    url:string;
    params:string;
    proc:TCallback;
    odp:String;
    procedure Odpowiedz;
  protected
    procedure Execute; override;
  public
    constructor Create(url, parametry: String; proc: TCallback);
  end;

implementation

constructor TWatek.Create(url,parametry:String; proc: TCallback);
begin
  inherited Create(false);
  self.url:=url;
  self.params:=parametry;
  self.proc:=proc;
  self.FreeOnTerminate:=true;
end;

procedure TWatek.Odpowiedz;
begin
  proc(odp);
end;

procedure TWatek.Execute;
begin
  sleep(5000); //tutaj wysylamy zapytanie do serwera
  odp:='ala ma kota';
  synchronize(odpowiedz);
end;

form1:

procedure TForm1.OdpowiedzSerwera(odp:String);
begin
  showmessage(odp);
end;

procedure TForm1.Button1Click(Sender: TObject);
var w:TWatek;
begin
 w:=TWatek.Create('www.4programmers.net', 'parametry', OdpowiedzSerwera );
end;
0

generalnie tak, tylko że

  1. przed odpaleniem proc wypadało by sprawdzić, czy przypadkiem nie jest nulem
  2. ładniej było by zamiast callbacka użyć eventu ale to już kwestia gustu
0

cimak wielkie dzięki. Działa nawet lepiej niż mogłem się spodziewać.

1 użytkowników online, w tym zalogowanych: 0, gości: 1