Formatka w wątku

0

Witam

Mam formatkę wywoływaną z biblioteki. Formatka ta dosyć często blokuje się na pewien czas uniemożliwiając przetwarzanie komunikatów w głównym wątku, czyli mówiąc prościej zawiesza aplikację. Eksperymentalnie utworzyłem tą formatkę (ramkę) w oddzielnym wątku i jako rodzica ustawiłem panel znajdujący się na głównej formatce. O dziwo wszystko działa bez problemu, komunikaty są przekazywane, główna formatka nie jest już blokowana.

Moje pytanie brzmi: Czy tworzenie kontrolek wizualnych i obsługa ich w oddzielnych wątkach jest dopuszczalna czy raczej niezalecana?

Całość funkcjonuje poprawnie, nie mam problemów z synchronizacją ani z rysowaniem. Nie wiem tylko jak "zlikwidować" taką kontrolkę bo zwolnienie takiego obiektu kończy się błędem nieprawidłowego dojścia okna.

0

W wątkach nie używamy VCL jeżeli chcemy operować na VCL (np. sterować paskiem postępu) to robimy to z użyciem Synchronize.

0
kAzek napisał(a)

W wątkach nie używamy VCL jeżeli chcemy operować na VCL (np. sterować paskiem postępu) to robimy to z użyciem Synchronize.

Wiem o tym. Ale co stoi na przeszkodzie jeśli nie odwołujemy się bezpośrednio do głównej formatki? Mówię o sytuacji w której każda z formatek w oddzielnym wątku ma własną pętle komunikatów.

0

No właśnie że masz problem z synchronizacją.
Zrób prosty eksperyment. Na formatkę postaw przycisk. Po kliknięciu na przycisk, odpal wątek który schowa ten przycisk Button1.Visible:=false; i na tym (wątek) skończy działanie. Po tej operacji niby wszystko ok ale błąd ci wyskoczy dopiero po zamknięciu formatki.

0
gamestone napisał(a)

Mówię o sytuacji w której każda z formatek w oddzielnym wątku ma własną pętle komunikatów.

bez obsługi kolejki komunikatów w wątku, które dane okno stworzył, daleko byś nie zaszedł, okno nawet by się nie pokazało ;] ale Ty to wiesz. gorzej z innymi...
dopóki właściwości formatki i jej dzieci zmienia naraz tylko jeden wątek ja nie widzę żadnych przeszkód. moje wątpliwości budzi ustawienie rodzica z innego wątku.

_13th_Dragon napisał(a)

No właśnie że masz problem z synchronizacją.
Zrób prosty eksperyment. Na formatkę postaw przycisk. Po kliknięciu na przycisk, odpal wątek który schowa ten przycisk Button1.Visible:=false; i na tym (wątek) skończy działanie. Po tej operacji niby wszystko ok ale błąd ci wyskoczy dopiero po zamknięciu formatki.

zauważyłeś, że tu masz formatkę stworzoną w wątku B, którą obsługuje i do której odwołuje się wątek B? Ty piszesz o sytuacji, kiedy formatkę tworzy główny wątek procesu A, a odwołuje się do niej wątek B.
jesteś pewien, że problem, o którym piszesz, zawsze wystąpi? moim skromnym zdaniem wystąpi losowo, ale za to od razu (EAccesViolation), a nie przy zamykaniu. ale nie mam Delphi od kilku lat, więc nie sprawdzę moich przypuszczeń.

0

to nie będzie działało. Fakt, że nie sypie się teraz to tylko szczęście, a to że wywala się przy zwalnianiu pokazuje jak mało tego szczęścia masz. Ostatnio było wałkowane jak uruchomić formę w osobnym wątku - trzeba wyrzeźbić tą formę w WinAPI i napisać do niej obsługę komunikatów - dopiero taka forma jest formą niezależną od głównego wątku aplikacji. Inna sprawa, że jakbyś nie tworzył formy bazując na klasie TForm z VCLa to ZAWSZE będzie ona tworzona w kontekście wątku głównego - VCL nie był, nie jest i zapewne za mojego życia nie będzie wielowątkowy!

0

A tak z ciekawości ?
Jest jakieś racjonalne uzasadnienie aby VCL był wielowątkowy ?

0

Tak a propos, zobacz sobie jak jest zrealizowany TIdThreadDialog i zrób podobnie.

0
Adamek Adam napisał(a)

A tak z ciekawości ?
Jest jakieś racjonalne uzasadnienie aby VCL był wielowątkowy ?

Uzasadnienie może być chociażby takie aby móc stworzyć np okno oczekiwania z animacją, która mogłaby się wykonywać nawet gdy forma główna nie odpowiada.
Drugi powód to wykorzystanie procesorów wielordzeniowych. Mam procka dwu rdzeniowego z HT, czyli w sumie 4 procesory logiczne. Jeśli wszystko wykonuje się w obrębie głównego wątku wykorzystuje maksymalnie 25% mocy obliczeniowej. Dodam ze nie mam wpływu na działanie formatek bo wszystko ładowane jest z bibliotek.

0
gamestone napisał(a)

Uzasadnienie może być chociażby takie aby móc stworzyć np okno oczekiwania z animacją, która mogłaby się wykonywać nawet gdy forma główna nie odpowiada.
wrzucałem jakiś miesiąc temu komponent, który to robi

Drugi powód to wykorzystanie procesorów wielordzeniowych. Mam procka dwu rdzeniowego z HT, czyli w sumie 4 procesory logiczne. Jeśli wszystko wykonuje się w obrębie głównego wątku wykorzystuje maksymalnie 25% mocy obliczeniowej. Dodam ze nie mam wpływu na działanie formatek bo wszystko ładowane jest z bibliotek.
od tego są wątki!!

0
ŁF napisał(a)

może na tym, że przeszedłem przez wszystkie wersje delphi od 2 do 7, może na tym, że znam tę część winapi, a może na tym, że programuję pod windows od czasu, kiedy przestałeś siusiać w pieluszki?

Pomijając fakt że wydaje się niemożliwym aby mogłeś programować pod windows zanim pojawił się na rynku pierwszy PC/XP, bo akurat kiedy się pojawił ja już byłem studentem na studiach wyższych, z twojej wypowiedzi wnioskuje że w twojej wiedzy są spore braki.
Poniższy kod w zależności od systemu windows, albo nie spowoduje żadnego błędu (nigdy) albo błąd pojawia się (za każdym razem) przy zamknięciu formatki.

unit Unit8;

interface

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

type
  TshThread = class(TThread)
  private
  protected
    procedure Execute;override;
  public
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    Th:TshThread;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TshThread.Execute;
var I:Integer;
begin
  try
    I:=0;
    while not Terminated do
    begin
      Inc(I);
      Form1.Button1.Caption:=IntToStr(I);
      Form1.Button1.Visible:=not Form1.Button1.Visible;
      Sleep(20);
    end;
  except
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if Th<>nil then
  begin
    Th.Terminate;
    Th.WaitFor;
    Th.Free;
    Th:=nil;
    Button1.Visible:=true;
  end
  else
  begin
    Th:=TshThread.Create(false);
  end;
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if Th<>nil then Button1Click(nil);
end;

end.
0
Misiekd napisał(a)

od tego są wątki!!

I właśnie dla tego próbuje stworzyć formatki w wątkach. Jak już wspomniałem wszystko ładowane jest z bibliotek (ActiveX), przez co mam dosyć ograniczone możliwości.

0
gamestone napisał(a)
Misiekd napisał(a)

od tego są wątki!!

I właśnie dla tego próbuje stworzyć formatki w wątkach. Jak już wspomniałem wszystko ładowane jest z bibliotek (ActiveX), przez co mam dosyć ograniczone możliwości.
co ma wspólnego AactiveX i forma? BTW jeśli ktoś pisząc ActiveXa nie zrobił go thread-safe to może on działać w wątku ale wcale nie musi i nic na to nie poradzisz

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