Czy źle tworzę wątek ze zmiennymi?

0

Na 4 programmers jest kilka słów o wątkach i tam gość używał constructor, no to utworzyłem wątek tak samo i działać działa, ale czy sposób na odpalanie wątku podając zmienne jest dobry, czy może jest inny sposób, lepszy i bez contructor?

Wybrane fagmenty kodu...

  public
    { Public declarations }
  end;

type
  TWatek = class(TThread)
  protected
    procedure Execute; override;
  private
    txt: String;
    liczba: Byte;
  public
    constructor Utworz(tekst: string; i: Byte);
  end;

//.........

procedure TForm1.Button1Click(Sender: TObject);
begin
  TWatek.Utworz('Testowanie', 113);
end;

{ TWatek }
procedure TWatek.Execute;
begin
  inherited;
  FreeOnTerminate := True;
  Form1.Memo1.Lines.Add(txt + IntToStr(liczba));
end;

constructor TWatek.Utworz(tekst: string; i: Byte);
begin
  inherited Create(False);
  txt := tekst;
  liczba := i;
end;

I tak ma być? Bo działać działa, ale może jest inny sposób, gdzie od razu podaję te dwie zmienne przy tworzeniu wątku i nie bawię się w pisanie konstruktora przypisującego zmienne do innych zmiennych? Bo to takie dziwne jest, podać raz zmienne i w konstruktorze przekazywać je kolejny raz...

0

Co rozumiesz poprzez "bez construtor"?
Klasę tak czy siak musisz stworzyć wywołując konstruktor,więc nie wiem do czego dążysz.
Btw, odwoływanie się do komponentów na formie w wątku jest niebezpieczne.

0

Chodziło mi o to bym w wątku miał raz podane zmienne np. (txt: String; liczba: Byte) i utworzył wątek tak jak zwykłą procedurę i nie musiałbym wtedy przypisywać tych zmiennych do kolejnych zmiennych identycznych, by je przekazać wątkowi, o to mi chodzi. Bo obecnie to mam 4 zmienne zamiast dwóch... i dwie zmienne podaję i one trafiają do kolejnych dwóch zmiennych, nie prościej byłoby mieć w wątku tylko dwie zmienne, a nie cztery? W teorii mógłbym olać wszystkie zmienne w wątku i zrobić dwie zmienne globalne i wtedy w buttonie kod wyglądałby tak:

txt := 'blabla';
liczba := 10;
Watek := TWatek.Create(False);

i w kodzie wątku, wątek pobierałby dane ze zmiennych globalnych. Podsumowując, nie musiałbym pisać kodu z konstruktorem przypisującym zmienne kolejnym zmiennym.

A swoją drogą, dlaczego odwoływanie się do komponentów w wątku jest niebezpieczne?

0

O ile dobrze zrozumiałem:
Posiadasz jakieś dwie zmienne lokalne/globalne o nazwach txt oraz liczba; wątek również posiada dwa takie pola, a Ty chcesz uniknąć powtarzania się w stylu TWatek.Create(txt, liczba);, prawda?
Jeżeli tak, to tego "problemu" nie da się ominąć, chyba że te zmienne są globalne - wtedy wątek może sam w konstruktorze pobrać sobie ich wartości i przypisać do pól (self.txt := txt; (...)).

i w kodzie wątku, wątek pobierałby dane ze zmiennych globalnych.

Jeżeli te zmienne nie są atomowe (a np.string nie jest), możliwe, że dostaniesz Access Violation.

A swoją drogą, dlaczego odwoływanie się do komponentów w wątku jest niebezpieczne?

Ponieważ całe VCL zostało projektowane pod jeden główny wątek; poczytaj o Synchronize (o ile nie pomyliłem się w nazwie).

0

Chyba musisz zacząć od podstaw i dowiedzieć się czym są klasy.
W konstruktorze najlepiej przekazywać wartości początkowe niezbędne do wystartowania wątku ponieważ jest to jedyna metoda, która wykonuje się przed Execute o ile wątek nie został zawieszony wcześniej. Pola prywatne txt i liczba są widoczne w całej klasie i możesz z nich korzystać także w Execute, jednak nie można im bezpośrednio przypisać wartości dlatego robi się to przez konstruktor. Można by to ominąć przez dodanie ich z modyfikatorem dostępu public, ale do czasu ich przypisania wątek musiałby być zawieszony.
Zresztą trudno streścić całą otoczkę związaną z OOP w jednym poście - koniecznie o tym poczytaj.

0

bardzo dziękuję wam za pomoc. Jeszcze ostatnie pytanie:
W tym ebooku na 4programmers jest taki kod:

constructor TGoThread.Create(Counter: Integer);
begin
  inherited Create(False); // wywołanie wątku
  FCounter := Counter; // przypisanie wartości do zmiennej
end;

co by się stało, gdybym wywalił z tego kodu słówko inherited? Jak w swoim przypadku w kodzie z tego tematu sprawdzam program bez słówka inherited to wszystko działa idealnie, identycznie jak ze słówkiem inherited więc skoro nie widać różnicy, to po co miałbym dopisywać słówko inherited? Do tej pory tego inherited to głównie używałem w zupełnie innych rzeczach jak np.

procedure TForm1.WMSysCommand(var msg: TWMSysCommand);
begin
  inherited;

  if (msg.CmdType = SC_MINIMIZE) then

i w takim przypadku to słówko inherited miało sens, bo dziedziczyło mi te różne rzeczy odpowiadające za minimalizację, maksymalizację, zamknięcie okna itd i bez tego słówka nie działałyby te funkcje, a tak to jedno słówko inherited się dopisało i już miało się z głowy wszystko, można było napisać co dodatkowo ma się stać podczas zminimalizowania okna np. migać ikonką lub cokolwiek innego. A w wątkach w przykładzie z tej książki itd to nie wiem za bardzo po co ten inherited jest skoro bez niego zmienne i tak przypisuje dobrze.
Wytłumaczy mi ktoś? :) Wolę zapytać niż dowiedzieć się przypadkiem w dalekiej przyszłości. I jeszcze raz dziękuję za poświęcony czas na mnie.

0

widziałem to już, ale to mi niewiele mówi. Podałem wam praktyczne przykłady i zapytałem dlaczego wszystko działa idealnie bez słówka inherited?

0

Bo akurat kompilator w tym przypadku:
inherited Create(False); // wywołanie wątku
Automatycznie wykrywa, że chcesz się odwołać do klasy-rodzica, tak więc to inherited w tym konkretnym przypadku nie robi różnicy.

WMSysCommand już natomiast nie zadziała bez inherited, ponieważ w funkcji/procedurze jest ono odpowiednikiem:

procedure TForm1.WMSysCommand(var msg: TWMSysCommand);
begin
  inherited; // -> TKlasaNadrzedna.WMSysCommand(msg);
 
  if (msg.CmdType = SC_MINIMIZE) then
0

dzięki

0

Kompilator nie zrobił tobie błędnego kodu bez inherited bo był w stanie odróżnić konstruktor nadrzędny po liście argumentów. Jeżeli nie byłoby takiej możliwości najprawdopodobniej wygenerował by sekwencję wywołania samego siebie co raczej nie skończy się niczym dobrym.

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