Pyt. dotyczące wyniku pracy wątku.

0

Witam.

Mam problem dot. wątków.
Chciałbym stworzyć w programie wątek i pobrać wynik jego działania.

Po krótce wygląda do tak, że wywołuję w aplikacji wcześniej przygotowany wątek metodą wątek.create(parametry). Wyświetla on na ekranie synchronizowanego messageboxa i w miejscu, w którym wywołałem wątek, chciałbym uzyskać rezultat zwrócony z właśnie przez messageboxa.

Jest to w ogóle możliwe? Bo jeśli nie, to moje pytanie nie ma sensu...

Pozdrawiam.

Problem rozwiązany 3 posty niżej, a profesjonalniej 6 postów niżej.

.

0

Nie wiem czy dobrze kombinuje, bo przekazywanie parametrow do wątku da się zrobić, a co do uzyskania w
nim rezultatów to ja bym dodal zmienną globalną i ją ustawiał w wątku, a póżniej sprawdzał co zwrociła, o
ile się nie mylę - to właśnie tak powinno się dać to rozwiązać. Ale może ktoś inny tutaj podpowie Ci lepiej.

0

kod

0

Rozwiązałem już to na "swój sposób".
Głównym założeniem było to, by z wątków, które nie były zsynchronizowane, wyświetlić messageboxa, który były zsynchronizowany i uzyskać jego rezultat.

(W programie używam AplhaSkinów i okienka asynchroniczne nie są oskinowanie ;s )

Jak sądzicie? Dobrze to zbudowałem, czy dało się jakoś szybciej / ładniej?

type
  Tmymsg = class(TThread)
    private
      _wiadomosc:string;
      _caption:string;
      _output:^integer;
      _icon:integer;
      procedure show;
      procedure execute; override;
    public
      finished:boolean;
      constructor Create(wiadomosc:string; caption:string; output:pointer; icon:integer=0);
  end;

constructor Tmymsg.Create(wiadomosc:string; caption:string; output:pointer; icon:integer=0);
begin
  _wiadomosc:=wiadomosc;
  _caption:=caption;
  _output:=output;
  _icon:=icon;
  finished:=false;
  inherited Create(False); // wywołanie wątku
end;

procedure Tmymsg.show;
begin
  _output^:=application.MessageBox(pchar(_wiadomosc), pchar(_caption), _icon);
end;

procedure Tmymsg.Execute;
begin
  Synchronize(show);
  finished:=true;
end;

Wywołuję to funkcją:

function mymsgbox(wiadomosc:string; caption:string; icon:integer=0):integer;
var
  q:Tmymsg;
begin
  q:=Tmymsg.Create(wiadomosc, caption, @result, icon);
  while not(q.finished) do
  begin
    sleep(10);
    application.ProcessMessages;
  end;
end;

A w samym kodzie docelowym:

if mymsgbox('tresc', 'caption', parametry)=6 then ...
0

to teraz powiedz mi

  1. dlaczego _output jest wskaźnikiem
  2. wiesz co robi synchronize
  3. sprawdzałeś czy wchodzi do petli zanim nie zamkniesz okienka
  q:=Tmymsg.Create(wiadomosc,caption,@result,icon);
  while not(q.finished) do
  1. po co w ogóle ten wątek
  2. co chcesz osiągnąć
0
  1. Użyłem wskaźnika, bo tak było mi wygodniej. W ciele wątku przekazuję sobie wskaźnik na zmienną wyjściową (wolałem tak niż przez referencję).

  2. Czemu użyłem synchronize? To jest tak: Mam sobie powiedzmy wątki które w jakiś tam sposób pracują sobie równolegle w programie. Cały program ma zbindowaną skórkę. Teraz, jeśli któryś wątek wywoła pytanie messagebox'em - wyświetli się ono poprawnie, ale bez skórki. Dlatego kombinowałem jakby tu stworzyć zsynchronizowaną procedurę, do której mogło by się odwołać wiele wątków (by tego samego kodu nie powielać w ciele każdego wątku).
    Wpadłem na pomysł, że stworzę wątek, który byłby w stanie zwrócić mi rezultat swojego działania, a jego jedynym zadaniem było by wyświetlenie messageboxa z zadanymi parametrami, z użyciem metody synchronize. <<skórka zadziała, ładnie, pięknie.
    I wiem co robi synchronize :) Pozwala na bezpieczne odwołanie się do elementu, z którego mogły by skorzystać dwa lub więcej wątów na raz. (Powiedzmy elementu formy.)

  3. Ja liczę na to, że on wejdzie do tej pętli i wiem, że tak się stanie. Pętla została stworzona tylko po to, by czekać na rezultat wątku. A jak nie wejdzie się do tej pętli to też nic się nie stanie.

  4. Już napisałem w punkcie 2. Tzn. nie widzę innej opcji. Może jest, ale ja na nią nie wpadłem.

  5. j.w.

0

Możesz to zrobić tak (bez wątku pomocniczego, po prostu dajesz tak w Twoim wątku)

wątek

unit Unit2;

interface

uses
  Classes;

type
  TMyEvent = procedure(const Wiadomosc: string; const Caption: string; var Result: integer; const Icon: integer = 0) of object;

  aaa = class(TThread)
  private
    FMyEvent: TMyEvent;
    FWiadomosc: string;
    FCaption: string;
    FResult: integer;
    FIcon: integer;

    procedure DoMyEvent;
  protected
    procedure Execute; override;
  public
    property OnMyEvent: TMyEvent read FMyEvent write FMyEvent;
  end;

implementation

uses
  SysUtils,
  Windows;
{ aaa }

procedure aaa.DoMyEvent;
begin
  if Assigned(FMyEvent) then
    FMyEvent(FWiadomosc, FCaption, FResult, FIcon);
end;

procedure aaa.Execute;
begin
  FreeOnTerminate := True;
  while not Terminated do
  begin
    Sleep(1000);

    //setki lini dalej :p
    FWiadomosc := 'jakis text do wyswietlenia';
    FCaption := 'i jej naglowek';
    FIcon := 0;
    Synchronize(DoMyEvent);
    if FResult = 1 then
    begin
      sleep(1000);
      FWiadomosc := 'wcisnales ' + IntToStr(FResult);
      FCaption := 'dupa dupa';
      FIcon := 0;
      Synchronize(DoMyEvent);
    end;
  end;
end;

end.

i jak to wywołać

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    procedure WatekOnMyEvent(const Wiadomosc: string; const Caption: string; var Result: integer; const Icon: integer = 0);
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  Unit2;

procedure TForm1.FormCreate(Sender: TObject);
begin
  with aaa.Create(True) do
  begin
    OnMyEvent := WatekOnMyEvent;
    Resume;
  end;
end;

procedure TForm1.WatekOnMyEvent(const Wiadomosc, Caption: string;
  var Result: integer; const Icon: integer);
begin
  Result := Application.MessageBox(PChar(Wiadomosc), PChar(Caption), Icon);
end;

end.
0

Mm... kod stoi na wyższym poziomie niż moje umiejętności, acz ogarniam jego działanie i dziękuję za przykład :))

Wypróbuję go zaraz.

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