Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TThread Execute Methode dauerhaft laufen lassen (https://www.delphipraxis.net/113665-tthread-execute-methode-dauerhaft-laufen-lassen.html)

sk0r 12. Mai 2008 18:46


TThread Execute Methode dauerhaft laufen lassen
 
Hi,

gibt es eine Möglichkeit, dass die Methode
Execute der erbenden TThread-Klasse, wie
wenn man mit WinAPI einen Thread erstellt und
ihn dauerhaft mit einer While-Schleife laufen
lässt, dauerhaft laufen zu lassen? Der Grund ist,
ich möchte eine Winsock-Klasse erstellen und
muss dort dauerhaft die Funktion recv() aufrufen
lassen.

MfG: sk0r

Luckie 12. Mai 2008 18:51

Re: TThread Execute Methode dauerhaft laufen lassen
 
Du hast die Lösung doch schon selber genannt. Ja das geht.

p0w3r5tr34m3r 12. Mai 2008 20:27

Re: TThread Execute Methode dauerhaft laufen lassen
 
Delphi-Quellcode:
while true do begin
  // code
  recv(s, buffer, sizeof(buffer));
  // code
end;
MfG

sirius 12. Mai 2008 21:08

Re: TThread Execute Methode dauerhaft laufen lassen
 
Du weißt aber, dass die Sockets von Windows auch andere Möglichkeiten anbieten, als das ständige Polling. --> WSAAsyncSelect

FAlter 12. Mai 2008 21:18

Re: TThread Execute Methode dauerhaft laufen lassen
 
Hi,

wenn du einen Thread in einer Schleife laufen lassen willst, nimm am besten eine Bedingung mit Terminated, also repeat ... until Terminated oder so. Falls du ihn dann doch Beenden möchtest, geht es dann ganz einfach über TThread.Terminate. So lange du das nicht aufrufst, wird dein Thread weiterlaufen (Vorausgesetzt es gibt keine unbehandelten Exceptions, kein break und kein exit in deinem Code).

Mfg
FAlter

sk0r 12. Mai 2008 21:27

Re: TThread Execute Methode dauerhaft laufen lassen
 
Naja, das Problem ist, wenn ich
Delphi-Quellcode:
procedure Thread.Execute;
begin
  while true do
  begin
    //Irgendwas machen
    Sleep(10);
  end;
end;
benutze, dann wird meine Hauptanwendung blockiert. :/

Delphi-Quellcode:
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

  thread = class(TThread)
    procedure Execute;
  end;

var
  Form1: TForm1;
  gthread: thread;

implementation

{$R *.dfm}

procedure thread.Execute;
begin
  while true do
  begin
    ShowMEssage('TEST');
    Sleep(10);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  gthread := thread.Create(true);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  gthread.Execute;
end;

end.

FAlter 12. Mai 2008 21:40

Re: TThread Execute Methode dauerhaft laufen lassen
 
Hi,

du darfst nicht direkt die Execute aufrufen. Stattdessen musst du den Thread mit Resume starten (oder du übergibst gleich false an den Thread, dann wird er sofort gestartet).

Und ich glaube, ShowMessage aus dem Thread aufzurufen fällt in die Kategorie, in welcher Synchronize angesagt ist. Nimm lieber eine MessageBox.

Mfg
FAlter

sirius 12. Mai 2008 21:47

Re: TThread Execute Methode dauerhaft laufen lassen
 
ein "override" wäre in der Deklaration der Methode execute noch sehr hilfreich.

sk0r 12. Mai 2008 21:51

Re: TThread Execute Methode dauerhaft laufen lassen
 
Ok, bei Resume bekomme ich nun einen abstrakten Error. ó_Ò

Kann jemand mal meinen Code ansehen? Wäre echt nett.

Delphi-Quellcode:
unit sockettest;

interface

uses
  SysUtils,
  Classes,
  Windows,
  Winsock;

type
  TSockThread = class(TThread)
    iSock: Cardinal;
    recvProc: procedure(szString: String);
    procedure Execute;
  end;

  TSmallSock = class
      constructor Create(Address: PChar; Port: Cardinal);
      procedure Free;
    private
      lpAddress: PChar;
      dwPort: Cardinal;
      iSock: Cardinal;
      WSAData: TWSAData;
      addrIn: TSockAddrIn;
      dwThreadID: Cardinal;
      gThread: TSockThread;
    public
      procRecv: procedure(szString: String);
      function DoConnect:Boolean;
      function SendString(szString: String):Boolean;
  end;


var gSmallSock: TSmallSock;

implementation

procedure TSockThread.Execute;
var
  mBuf: array[0..1000-1] of Char;
begin
  if recv(gSmallSock.iSock, mBuf, sizeof(mBuf), 0) <> SOCKET_ERROR then
  begin
    if mBuf <> '' then
    begin
      recvProc(mBuf);
      mBuf := '';
    end;
  end;
end;

constructor TSmallSock.Create(Address: PChar; Port: Cardinal);
begin
  lpAddress := Address;
  dwPort := Port;
end;

function TSmallSock.DoConnect:Boolean;
begin
  result := false;
  try
    if WSAStartup(MAKEWORD(2, 2), WSAData) <> SOCKET_ERROR then
    begin
      iSock := socket(AF_INET, SOCK_STREAM, 0);
      if iSock = SOCKET_ERROR then exit;

      addrIn.sin_family := AF_INET;
      addrIn.sin_port := htons(dwPort);
      addrIn.sin_addr.S_addr := inet_addr(lpAddress);

      if connect(iSock, addrIn, sizeof(addrIn)) <> SOCKET_ERROR then
      begin
        gThread := TSockThread.Create(true);
        gThread.iSock := iSock;
        gThread.recvProc := procRecv;
        gThread.Resume;

        result := true;
      end;
    end;
  except
    WSACleanup;
  end;
end;

function TSmallSock.SendString(szString: String):Boolean;
begin
  result := false;

  if send(iSock, szString, length(szString), 0) <> SOCKET_ERROR then
    result := true;
end;

procedure TSmallSock.Free;
begin
  inherited Free;

  gThread.DoTerminate;
  WSACleanup;
end;

end.

sirius 12. Mai 2008 21:53

Re: TThread Execute Methode dauerhaft laufen lassen
 
Zitat:

Zitat von sk0r
Ok, bei Resume bekomme ich nun einen abstrakten Error. ó_Ò

Siehe Post #8 :mrgreen:

FAlter 12. Mai 2008 21:53

Re: TThread Execute Methode dauerhaft laufen lassen
 
Hi,

Die Lösung steht hier:

Zitat:

Zitat von sirius
ein "override" wäre in der Deklaration der Methode execute noch sehr hilfreich.

Mfg
FAlter

[edit] Mal wieder kein roter Kasten. :P Sonst habe wenigstens ich immer Glück. [/edit]

sk0r 12. Mai 2008 22:06

Re: TThread Execute Methode dauerhaft laufen lassen
 
Ok, danke für eure Hilfe. Hab ich wohl eine Sache der Grundkenntnisse vergessen. :/

Muetze1 12. Mai 2008 22:33

Re: TThread Execute Methode dauerhaft laufen lassen
 
... und deine Procedure "Free" kannst du auch gleich mal in die Tonne drücken und als
Delphi-Quellcode:
Destructor Destroy; override;
gleich mal neu auferstehen lassen...

Luckie 13. Mai 2008 08:12

Re: TThread Execute Methode dauerhaft laufen lassen
 
Hier: http://delphitutorials.michael-puff.de gibt es auch ein entsprechendes Tutorial.

sirius 13. Mai 2008 08:18

Re: TThread Execute Methode dauerhaft laufen lassen
 
Noch etwas:
Du greifst in deinem Thread auf eine globale Variable zu (gSmallSock.iSock). Du hast doch dein Sockethandle bereits innerhalb deines Threadobjektes. Das kannst du doch benutzen.
Die Procedure "recvProc" muss Threadsafe sein oder du musst vorher synchronisieren.

sk0r 17. Mai 2008 13:20

Re: TThread Execute Methode dauerhaft laufen lassen
 
Darf ich fragen, was Du mit Threadsafe genau meinst?^^

sirius 17. Mai 2008 17:23

Re: TThread Execute Methode dauerhaft laufen lassen
 
Du darfst in einer Funktion/Unit/Klasse/etc. , die du ThreadSafe haben möchtest, niemals auf Variablen oder Speicher zugreifen, die auch ausserhalb dieses Objektes genutzt werden (oder du musst synchronisieren).
Für dich bedeutet dass, dass du in RecvProc nur lokale Variablen verwenden darfst und vor allem keine GUI.

sk0r 17. Mai 2008 18:11

Re: TThread Execute Methode dauerhaft laufen lassen
 
Und wie kann ich es machen, damit ich auf globale Variablen/Speicher zugreifen darf, ohne Fehler zu verursachen?
Weil, irgendwie muss es ja gehen, die TClientSocket Komponente arbeitet doch auch mit Threads!?

sirius 17. Mai 2008 19:32

Re: TThread Execute Methode dauerhaft laufen lassen
 
Delphi-Quellcode:
type
  TSockThread = class(TThread)
    iSock: Cardinal;
    recvProc: procedure(szString: String);
    procedure Execute; override;
  protected
    FBuffer:string;
    procedure CallRecvProc;
  end;

  TSmallSock = class
      constructor Create(Address: PChar; Port: Cardinal);
      procedure Free;
    private
      lpAddress: PChar;
      dwPort: Cardinal;
      iSock: Cardinal;
      WSAData: TWSAData;
      addrIn: TSockAddrIn;
      dwThreadID: Cardinal;
      gThread: TSockThread;
    public
      procRecv: procedure(szString: String);
      function DoConnect:Boolean;
      function SendString(szString: String):Boolean;
  end;


var gSmallSock: TSmallSock;

implementation

procedure TSockThread.CallRecvProc;
begin
  recvProc(FBuffer);    
end;
procedure TSockThread.Execute;
var
  mBuf: array[0..1000-1] of Char;
begin
  if recv(iSock, mBuf, sizeof(mBuf), 0) <> SOCKET_ERROR then
  begin
    if mBuf <> '' then
    begin
      FBuffer:=mBuf;
      synchronize(CallRecvProc);
      mBuf := '';
    end;
  end;
end;

sk0r 29. Mai 2008 15:03

Re: TThread Execute Methode dauerhaft laufen lassen
 
Ok, eine Frage habe ich noch. :/

Wenn ich TClientSocket benutze und es kommen Daten rein, dann bleibt das Programm
"hängen", bis TClientSocket.OnRecieve ausgeführt wurde. Wie kann ich das realisieren?
Weil im Moment wird es ja "gleichzeitig" ausgeführt. Ich hoffe, ihr wisst, was ich meine. :/

sirius 29. Mai 2008 20:14

Re: TThread Execute Methode dauerhaft laufen lassen
 
Nö, ich verstehe nicht, was du meinst.
Ist Tclientsocket jetzt von dir , oder meinst du die Komponente von Delphi? Und die willst du jetzt in einen Thread packen? Oder was meinst du mit warten?

Edit: Ich würde dir übrigens raten einen neuen Forum-Thread zu erstellen. Dann reagieren meist mehr Leute und ausserdem ist es für das gesamte Forum besser, wegen der Suche.
(Kannst ja einen Link zu diesme Thread setzen)


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:34 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz