Sterowanie watkiem w dll (Stop,pause,Resume)

0

W jaki sposob moge sterowac watkiem tworzonym w dll chodzi o pause resume terminate z poziomu aplikacji?

0

Nie używałem nigdy wątków w dllach, ale jak rozumiem zadeklarowanie
zmiennej globalnej typu TThread i obslugiwanie jej przez eksportowane
procedury nie działa wcale / nie działa prawidłowo, o ile to sprawdziłeś?

0

Cos takiego probowalem ale nie dziala

unit Unit1;

interface

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

Type
 TTestThread = class(TThread)
  private
  protected
    procedure Execute; override;
  public
   I :Integer;
  end;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    Button5: TButton;
    Button4: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
    Test    : TTestThread;
    Licznik : Integer;
  public
    { Public declarations }
  end;



  procedure CreateTheard(Watek:TTestThread); stdcall external 'test.dll' name 'CreateTheard';

var
  Form1: TForm1;

implementation

{$R *.dfm}
procedure TTestThread.Execute;
begin
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
Test.Suspend;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
Test.Resume;
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
Test.Terminate;
end;


procedure TForm1.Timer1Timer(Sender: TObject);
begin
 Caption:=IntToStr(Test.I);
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
   Caption:=IntToStr(Test.I);
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  CreateTheard(Test);
end;

end.
library test;


uses
  SysUtils,
  Classes,Dialogs;

Type
 TTestThread = class(TThread)
  private
  protected
    procedure Execute; override;
  public
   I :Integer;
  end;

{$R *.res}

procedure TTestThread.Execute;
begin
  ShowMessage('watek Start');
  I:=1;
  FreeOnTerminate := True;
  while not (Terminated) do
  begin
    Sleep(1000);
    Inc(I);
  end;

  ShowMessage('watek end');
end;

procedure CreateTheard(Watek:TTestThread); stdcall;
begin
  Watek:=TTestThread.Create(True);
  Watek.Resume;
end;

exports  // eksportuj procedurę
  CreateTheard name 'CreateTheard';

begin
end.
  
1

A czy Ty myślisz co robisz w ogóle? Przecież chciałeś wątek obslużyć w dllce.
To na logikę w dllce powinien być ten wątek jako zmienna globalna i to typu
TThread, a eksportowane na zewnątrz procedury mają nim "sterować", masz
jakieś problemy z rozumieniem polskiego języka w piśmie? Przecież Ty w tej
swojej dllce tylko tworzysz wątek i jest to jedyna eksportowana procedura, a
czy zadziała po tym jak spróbujesz to zrobić tak jak się powinno próbowac to
nie gwarantuję. Ale teraz w kodzie programu i dll, robisz zupełnie coś innego.

EDIT: aż sprawdziłem i nie mam pojęcia dlaczego sobie generujesz sam jakieś
problemy zamiast sprawdzić, według mnie wszystko działa jak należy. A Label
dałem po to żeby nie było problemów, bo nieraz wątki nie moga wpływać i to
nawet w tym samym programie na etykiete samej formatki. Potrzebne jest w
takim wypadku Synachronize. No ale tutaj wszystko działa, tylko że dll nieco
"spuchł", ale to nic dziwnego przy użyciu dodatkowych modułów. Oto kod dll:

library test;

uses
  Classes, StdCtrls, SysUtils;

type
  TMainThr = class(TThread)
  private
    FWhatLabel : TLabel;
  public
    constructor Create(WhatLabel : TLabel);
  protected
    procedure Execute; override;
  end;

var
  AThr : TThread;

constructor TMainThr.Create(WhatLabel : TLabel);
begin
  inherited Create(False);
  FWhatLabel := WhatLabel;
end;

procedure TMainThr.Execute;
begin
  Randomize;
  while Terminated = False do
  begin
    FWhatLabel.Caption := IntToStr(Random(99999));
    Sleep(100);
  end;
end;

procedure StartThread(ALabel : TLabel) stdcall;
begin
  if AThr = nil then
  begin
    AThr := TMainThr.Create(ALabel);
  end
  else
  begin
    AThr.Resume;
  end;
end;

procedure StopThread; stdcall;
begin
  if AThr <> nil then
  begin
    AThr.Terminate;
    AThr.Free;
    AThr := nil;
  end;
end;

procedure PauseThread; stdcall;
begin
  if AThr <> nil then
  begin
    AThr.Suspend;
  end;
end;

exports
  StartThread,
  StopThread,
  PauseThread;

begin
end.

Kod programu. Trzy zwykłe Buttony i Label, o standadowych nazwach.
buttony muszą mieć ustawione OnClick. Nadal nie rozumiem - z czym
masz u siebie problem. Chociaż Ty zignorowałeś moje rady i coś tam
po swojemu tworzysz. Jak wątek dalej nie działa to wklej jego kod z
użyciem w dllce. Chociaż prawidlowo napisany każdy będzie działał:

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1 : TButton;
    Label1 : TLabel;
    Button2 : TButton;
    Button3 : TButton;
    procedure FormCreate(Sender : TObject);
    procedure Button1Click(Sender : TObject);
    procedure Button2Click(Sender : TObject);
    procedure Button3Click(Sender : TObject);
  private
  public
  end;

var
  Form1 : TForm1;
  StartThread : procedure(ALabel : TLabel); stdcall;
  StopThread : procedure stdcall;
  PauseThread : procedure stdcall;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender : TObject);
var
  DllH : THandle;
begin
  Button1.Enabled := False;
  Button2.Enabled := False;
  Button3.Enabled := False;
  DllH := LoadLibrary('test.dll');
  if DllH <> 0 then
  begin
    StartThread := GetProcAddress(DllH, 'StartThread');
    StopThread := GetProcAddress(DllH, 'StopThread');
    PauseThread := GetProcAddress(DllH, 'PauseThread');
    if (@StartThread = nil) or (@StopThread = nil) or (@PauseThread = nil) then
    begin
      Exit;
    end;
  end
  else
  begin
    Exit;
  end;
  Button1.Enabled := True;
  Button2.Enabled := True;
  Button3.Enabled := True;
end;

procedure TForm1.Button1Click(Sender : TObject);
begin
  StartThread(Label1);
end;

procedure TForm1.Button2Click(Sender : TObject);
begin
  PauseThread;
end;

procedure TForm1.Button3Click(Sender : TObject);
begin
  StopThread;
end;

end.
0

Nawet nie wiedziałem ze tak to można napisać z wątków nie jestem zbyt dobry.
Podany przez ciebie przyklad działa jak należy.Teraz moje nastepne pytanie co by trzeba dodac lub zmienic aby dll działała dla dynamicznej tablicy TLabel.Podejrzewam że bedzie potrzebyny uchwyt watku

0

Przekazujesz tablicę jako parametr do procedury, najlepiej poprzedzoną słowem var i
na niej operujesz, jeżeli konieczna jest pętla z operacjami na całej tej tablcy to robisz
ją od najnizszego do najwyższego elementu czyli na przykład tak jak poniżej. Myślę,
że nie powinno być z tym problemów. Jeżeli tablica ma zawierać dane typu string, to
zamiast string używasz typ PChar w dllce. Natomiast jeżeli to ma być TLabel lub inny
obiekt to możesz go przechowywać na liście wskaźników TList lub też jako obiekty na
choćby TStringList gdzie robisz AddObject('', JakisLabel); zaś do konkretnego obiektu
odwołujesz się przez TLabel*TwojaStringLista.OBjects[IndeksOdZera] i chyba tyle ;/
Ja od kąd dowiedziałem się, a bylo to nie tak dawno, bo może z rok temu, że da się
przechowywac wskaźniki na obiekty na TList i w ogołe obiekty na komponentach - z
danymi przechowywnymi jako TStrings oraz na ListView i TreeView czy StringGrid z
łatwością można przchowywac obiekty, to nie srosuje już wcale tablic dynamicznych
tylko właśnie te obiekty. Oczywiście w VCL gdzie wiadomo exe i tak Ci "spuchnie".

  for I := Low(Tablica) to Hidgh(Tablica) do // ...

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