Kilka wątków zmieniających Caption Labeli.

Odpowiedz Nowy wątek
2015-01-03 14:19
0

Witam,
Od kilku dni próbuję napisać aplikację w delphi 7, która zmieniłaby captiony 3 labeli ale w 3 osobnych wątkach (label1.caption zmienia się w pierwszym wątku, label2.caption zmienia się w drugim i label3.caption zmienia się w 3 wątku). Ale chciałbym by wszystkie captiony zmieniły się w dokładnie tym samym momencie.
Na 4programmers znalazłem taki, kod, losuje on jakąś maksymalna wartość progressbaru i przypisuje do każdego wartość licznika "i" w pętli aż do wylosowanej maksymalnej wartosci. Pierwszy problem jaki zauważyłem, to to że nie dzieje się to synchronicznie, zawsze jest jakaś przerwa między "przeskakiwaniem tych kresek". A drugi problem jest taki, że gdy na formę wrzucę jakiś label i chcę zmienić jego caption w procedurze Execute to wywala mi:

[Pascal Error] Unit1.pas(1): Unable to invoke Code Completion due to errors in source code
Ciekawa też rzecz jest taka, że jak z menu wybiorę stworzenie nowego wątku to tworzy mi jakby drugi plik z kodem "Unit2", a cała forma jest na Unit1 i co bym nie wrzucił (button, edit, label, memo) to stworzony wątek już go nie rozpozna :P

unit Unit1;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, StdCtrls;
 
type
  TForm1 = class(TForm)
    btnGo: TButton;
    ProgressBar1: TProgressBar;
    ProgressBar2: TProgressBar;
    ProgressBar3: TProgressBar;
    procedure btnGoClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
 TGoThread = class(TThread)
  private
    FV : Integer; // wylosowana liczba
    FCounter : Integer; // numer wątku
    pozycja : Integer;
    procedure SetProprties;
  protected
    procedure Execute; override;
  public
    constructor Create(Counter : Integer);
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
procedure TForm1.btnGoClick(Sender: TObject);
begin
{ utworzenie trzech wątków }
  TGoThread.Create(1);
  TGoThread.Create(2);
  TGoThread.Create(3);
end;
 
constructor TGoThread.Create(Counter: Integer);
begin
  inherited Create(False); // wywołanie wątku
  FCounter := Counter; // przypisanie wartości do zmiennej
end;
 
procedure TGoThread.Execute;
var
  i : Integer;
begin
  FreeOnTerminate := True; // zwolnij po zakończeniu wątku
 
  Randomize;
  FV := Random(1000);
  { odnalezienie komponentu na formularzu }
  TProgressBar(Form1.FindComponent('ProgressBar' + InttoStr(FCounter))).Max := FV;
 
  for i := 0 to FV do
  begin
    Sleep(10);
    pozycja := i;
    Synchronize(SetProprties);
  end;
end;
 
procedure TGoThread.SetProprties;
begin
    TProgressBar(Form1.FindComponent('ProgressBar' + IntToStr(FCounter))).Position := pozycja;
end;
 
end.
edytowany 2x, ostatnio: furious programming, 2015-01-04 15:34

Pozostało 580 znaków

2015-01-03 14:53
0

Więc niech wątki zmieniają jakieś trzy niezależne zmienne (np właściwość Hint). Uwaga, synchronizacja nadal obowiązuje.
Natomiast jakiś timer przypisuje z Hint do Caption.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
ja wiem, ze głupi pomysł jeśli działa to nie jest głupi ale bez przesady... - abrakadaber 2015-01-03 16:03

Pozostało 580 znaków

2015-01-03 15:05
0

pod D2010 podany kod działa bez problemu
co do wątku w oddzielnym unice , to pewnie brakuje w nim

uses unit1; 

i jeszcze jedno , każdy wątek po utworzeniu żyje swoim życiem , nie ma żadnej gwarancji że aktualizacje captionów i progressbarów będą się wykonywały synchronicznie
jest raczej pewne że kolejność aktualizacji będzie zupełnie przypadkowa
jeśli chcesz wszystkie obiekty aktualizować synchronicznie , to najprościej zrobić to w jednym wątku
oczywiście można by zbudować mechanizm synchronizacji trzech wątków tak aby aktualizacje odbywały się synchronicznie

edytowany 3x, ostatnio: grzegorz_so, 2015-01-03 15:39
Założę się, że pytacz przyleci i powie "nie działa wyskakuje błąd" :D - babubabu 2015-01-03 15:36
"oczywiście można by zbudować mechanizm synchronizacji trzech wątków tak aby aktualizacje odbywały się SYNCHRONICZNIE"<br /> więc po zwróceniu uwagi przez @abrakadaber'a doprecyzuję:<br /> "oczywiście można by zbudować mechanizm synchronizacji trzech wątków tak aby aktualizacje odbywały się w ZADANEJ KOLEJNOŚCI" - grzegorz_so 2015-01-03 16:32
raczej chodziło mi o to uses... - babubabu 2015-01-03 17:22

Pozostało 580 znaków

2015-01-03 16:06
1

Ogólnie - tak się nie da. Nie da się ponieważ zmiany w UI mogą być robione TYLKO z poziomu wątku głównego. Koniec, kropka. Ten fakt determinuje stwierdzenie, że jednocześnie się nie da.


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2015-01-03 16:21
0

masz rację, niezbyt precyzyjnie się wyraziłem.
mówiąc o zbudowaniu własnego mechanizmu synchronizacji myślałem o stworzeniu czegoś takiego aby aktualizacje obiektów w trzech oddzielnych wątkach wykonywały się zawsze w ustalonej kolejności: label1,label2,label3,label1,label2 ......
a równoczesna ich aktualizacja , tak jak piszesz , nie jest możliwa
zresztą sama metoda Synchronize wykonuje się w kontekście wątku głównego

edytowany 2x, ostatnio: grzegorz_so, 2015-01-03 16:26

Pozostało 580 znaków

2015-01-03 16:42
0
grzegorz_so napisał(a):

zresztą sama metoda Synchronize wykonuje się w kontekście wątku głównego

tak, tylko że jak wywołasz z trzech wątków synchronize nawet jednocześnie (bo może się tak zdarzyć) to i tak wątek główny jest jeden i on te wywołania "wewnętrznie" będzie kolejkował i tego się nie przeskoczy


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2015-01-03 16:44
0

ależ dokładnie tak będzie , zupełna zgoda
myślałem o stworzeniu mechanizmu kolejkującego "synchronize" z poszczególnych wątków, tak aby były wywoływane w zadanej kolejności
oczywiście mechanizm należało by zaimplementowac w samym wątku, tak aby wątek czekał na swoją kolej z wywołaniem swojego "synchronize"

edytowany 3x, ostatnio: grzegorz_so, 2015-01-03 16:49

Pozostało 580 znaków

2015-01-03 16:58
0

tylko czy to ma sens bo może się zdarzyć (i pewnie nie będzie to wyjątek), że wątek 1 "obróci się" dwa razy a wątek 2 i 3 tylko raz. Potem 1 wcale a 2 np. trzy razy. I już całe kolejkowanie (zbieranie zawsze wyników z trzech wątków) nie ma sensu. Dlatego ktoś wymyślił wątki aby kawałki kodu mogły się wykonywać niezależnie od siebie


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

2015-01-03 17:05
0

skutek będzie taki że najwolniejszy w danym cyklu wątek będzie wstrzymywał pozostałe .
a czy ma sens ??? pytający postawił taki problem więc stąd dyskusja .
Chociaż pewnie dało by się znaleźć sytuacje w których taki mechanizm synchronizacji cykli wątków mógł by mieć sens.

edytowany 1x, ostatnio: grzegorz_so, 2015-01-03 18:21

Pozostało 580 znaków

2015-01-03 18:29
0

Trochę ściema była z tymi captionami, ogólnie miał to być program oparty na komponencie THGG (który o dziwo jeszcze działa), wysyłający z x numerów x wiadomości w tym samym czasie (tak tak, wiem że pomyślicie, że to spam, ale chodziło mi raczej o reklamę). W C napisałem aplikację konsolową pod Debianem, opartą na bibliotece libgadu, ale chciałem żeby to jakoś wyglądało i wziąłem się za delphi 7 :P

Tu jest wszystko na jedno kopyto w głównym wątku, program po kliknięciu logowania albo wysłania ścina na czas wykonywania np. pętli. Chodziło mi o wysyłanie tych wiadomości z innego/ych wątku/ów.

unit ggy;
 
interface
 
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, HGG,
  ExtCtrls, StdCtrls;
 
type
  Tsend = class(TForm)
    vnumber_label: TLabel;
    vnumber: TEdit;
    vmsg_label: TLabel;
    vmsg: TEdit;
    login: TButton;
    logout: TButton;
    timer: TTimer;
    HGG1: THGG;
    exit: TButton;
    start: TButton;
    HGG2: THGG;
    HGG3: THGG;
    HGG4: THGG;
    HGG5: THGG;
    HGG6: THGG;
    HGG7: THGG;
    HGG8: THGG;
    HGG9: THGG;
    HGG10: THGG;
    HGG11: THGG;
    HGG12: THGG;
    HGG13: THGG;
    HGG14: THGG;
    HGG15: THGG;
    HGG16: THGG;
    HGG17: THGG;
    HGG18: THGG;
    HGG19: THGG;
    HGG20: THGG;
    HGG21: THGG;
    HGG22: THGG;
    HGG23: THGG;
    HGG24: THGG;
    HGG25: THGG;
    HGG26: THGG;
    HGG27: THGG;
    HGG28: THGG;
    Button1: TButton;
    pass: TEdit;
    Label1: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Label2: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    Label7: TLabel;
    Label8: TLabel;
    Label9: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label14: TLabel;
    Label15: TLabel;
    Label16: TLabel;
    Label17: TLabel;
    Label18: TLabel;
    Label19: TLabel;
    Label20: TLabel;
    Label21: TLabel;
    HGG29: THGG;
    HGG30: THGG;
    HGG31: THGG;
    HGG32: THGG;
    HGG33: THGG;
    HGG34: THGG;
    HGG35: THGG;
    HGG36: THGG;
    HGG37: THGG;
    HGG38: THGG;
    HGG39: THGG;
    HGG40: THGG;
    HGG41: THGG;
    HGG42: THGG;
    HGG43: THGG;
    HGG44: THGG;
    HGG45: THGG;
    HGG46: THGG;
    HGG47: THGG;
    HGG48: THGG;
    HGG49: THGG;
    HGG50: THGG;
    HGG51: THGG;
    HGG52: THGG;
    HGG53: THGG;
    HGG54: THGG;
    HGG55: THGG;
    HGG56: THGG;
    HGG57: THGG;
    HGG58: THGG;
    HGG59: THGG;
    HGG60: THGG;
    HGG61: THGG;
    HGG62: THGG;
    HGG63: THGG;
    HGG64: THGG;
    HGG65: THGG;
    HGG66: THGG;
    HGG67: THGG;
    HGG68: THGG;
    HGG69: THGG;
    HGG70: THGG;
    HGG71: THGG;
    HGG72: THGG;
    HGG73: THGG;
    HGG74: THGG;
    HGG75: THGG;
    HGG76: THGG;
    HGG77: THGG;
    HGG78: THGG;
    HGG79: THGG;
    HGG80: THGG;
    HGG81: THGG;
    HGG82: THGG;
    HGG83: THGG;
    HGG84: THGG;
    HGG85: THGG;
    HGG86: THGG;
    HGG87: THGG;
    HGG88: THGG;
    HGG89: THGG;
    HGG90: THGG;
    HGG91: THGG;
    HGG92: THGG;
    HGG93: THGG;
    HGG94: THGG;
    HGG95: THGG;
    HGG96: THGG;
    HGG97: THGG;
    HGG98: THGG;
    HGG99: THGG;
    HGG100: THGG;
    procedure exitClick(Sender: TObject);
    procedure loginClick(Sender: TObject);
    procedure logoutClick(Sender: TObject);
    procedure startClick(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
const
  txtPlik = 'dane.txt';
 
var
  send: Tsend;
  Tablica: array[1..100] of Integer;
  txtDane :String;
  TF      :Text;
  a       :Integer;
 
implementation
 
{$R *.dfm}
 
procedure Tsend.exitClick(Sender: TObject);
begin
close;
end;
 
procedure Tsend.loginClick(Sender: TObject);
var
   I: Integer;
begin
For I:=1 To a-1 do
begin
THGG(FindComponent('hgg'+IntToStr(I))).Number:=Tablica[I];
THGG(FindComponent('hgg'+IntToStr(I))).Password:=pass.Text;
THGG(FindComponent('hgg'+IntToStr(I))).Status:=1;
THGG(FindComponent('hgg'+IntToStr(I))).Connect(500);
end;
 
end;
procedure Tsend.logoutClick(Sender: TObject);
var
   I: Integer;
begin
For I:=1 To a-1 do
begin
THGG(FindComponent('hggg'+lntToStr(I))).Status:=0;
end;
 
end;
procedure Tsend.startClick(Sender: TObject);
var
   I: Integer;
begin
 
For I:=1 To a-1 do
THGG(FindComponent('hgg'+lntToStr(I))).123,vmsg.text,);
 
end;
 
procedure Tsend.Button1Cl1ck(Sender: TObject);
begin
a:=1;
AssignFile(TF, txtPlik);
If Not FileExists(txtPlik) Then
begin
  ReWrite(TF);
  ShowMessage('Utworzono plik dane.txt, uzupelnij go lista numerow i ponownie wczytaj.');
  end;
Reset(TF);
while not EOF(TF) do
begin
txtDane:='';
ReadLn(TF, txtDane);
Tablica[a]:=StrToInt(txtDane);
a:=a+1;
end;
CloseFile(TF);
 
end;
 
procedure Tsend.FormCreate(Sender: TObject);
begin
 
end;
 
end.

Wprowadziłem kilka błędów celowo :P

edytowany 3x, ostatnio: Authh, 2015-01-03 18:34
ROTFL i poważnie na tej formie jest nadźgane 100 komponentów ręcznie? Jak chcesz rozsyłać niechciane treści reklamowe to oczywiście jesteś usprawiedliwiony - bo to wcale nie wpisuje się w definicję SPAMu -,-' - szopenfx 2015-01-03 18:52
łaaaaaaał, ale tego dużo :D - furious programming 2015-01-04 15:36

Pozostało 580 znaków

2015-01-03 18:46
0

Całkiem źle się za to zabrałeś...
Komponent THGG "wkładasz" w wątek. Wątek ma generalnie dwa zadania - 1 - zalogować się do GG i 2 - wysłać wiadomość na przekazaną listę numerów GG. Teraz każdy wątek ma swoich "klientów" do obsłużenia i nie blokuje wątku głównego. A dlaczego nie wysyłać jeden wątek jedna wiadomość? bo po pierwsze wątki "kosztują" zasoby a i liczba gniazd dostępnych w systemie jest ograniczona. O ile odpalenie 50 czy 100 to nie zbrodnia to już np. 10000 to morderstwo. A po drugie przy dużej ilości wątków może być wolniej zamiast szybciej.


Chcesz pomocy - pokaż kod - abrakadabra źle działa z techniką.

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

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