Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Create oder BeginThread aus Thread Klasse aufrufen !?


tamato76 - Sa 23.10.10 14:37
Titel: Create oder BeginThread aus Thread Klasse aufrufen !?
Hallo zusammen!

Ich bin nun seit kurzem auf Delphi gewechselt, und programmiere an einer Server Anwendung.
Dabei rufe ich aus der main Unit einen (Server) Thread von der Klasse TThread auf, welcher
sich in einer eigenen Unit befindet.
Diese Anwendung funktioniert auch soweit, aber nur für einen Client.

Um nun mehreren Clients einen Verbindungsaufbau zu erlauben, muss ich im Server Thread wiederum
für jeden Client Verbindungsaufbau einen Thread starten, und genau da liegt mein Problem :-(
Ich habe versucht das MultiThreading mit Create- oder BeginThread zu verwirklichen, leider ohne Erfolg.

Beim Kompellieren bekomme ich eine Fehlermeldung mit ... "access violation at 0x...."
Auch weiß ich nicht, ob ich den Socket Handle richtig an die Thread Funktion übergeben habe ....

Anbei habe ich einen Teil des source codes gepostet. Vielleicht, Hoffentlich kann mir dabei jemand weiterhelfen!!

Vielen Dank schon mal im vorraus!!


delfiphan - Sa 23.10.10 14:45

Eines was mir auffällt: Der Callback in BeginThread muss eine einfache Adresse sein. Du übergibst die Adresse einer Methode of object; das läuft wahrscheinlich schief, weil da die Parameterübergabe nicht korrekt verläuft.

Wieso arbeitest du direkt mit dem Betriebssystem; es gibt doch fertige Klassen für TCP Verbindung und Threading.


tamato76 - Sa 23.10.10 14:59

Hi Delphifan!

Das heißt, wenn ich meine GetMessage Prozedur nicht von der Klasse ServerTh ... ableite, sollte es funktionieren
wenn ich dich richtig verstehe!??


jaenicke - Sa 23.10.10 15:36

user profile icontamato76 hat folgendes geschrieben Zum zitierten Posting springen:
Beim Kompellieren bekomme ich eine Fehlermeldung mit ... "access violation at 0x...."
Beim Kompilieren? Bist du sicher? :gruebel:
Ich vermute doch eher, wenn das Programm läuft, oder?

Wenn ich das bei meinem ersten schnellen Blick (hab grad noch was zu tun) richtig gesehen habe, synchronisierst du PrintLine nicht. Da du vermutlich dort eine visuelle Komponente ansprichst, gibt es entsprechend Probleme.

Ich schaue nachher noch einmal genauer drauf.


tamato76 - Sa 23.10.10 16:51

Du hast natürlich recht, die access violation kommt beim ausführen des Programmes!
Und ja .. schreibe über PrintLine die empfangenen Daten in eine Memo Box.

Vielen Dank


jaenicke - Sa 23.10.10 17:05

Dass die Fehlermeldung dort kommt, war mir schon klar. Ich wollte nur deutlich machen, dass du schon ein wenig auf die Terminologie achten solltest, denn an anderer Stelle entstehen so vielleicht Missverständnisse. ;-)

Ok, dann kann das so nicht gut gehen, wenn du da auf ein Memo quasi direkt aus dem Thread zugreifst.

Hier einmal ein Beispiel wie sowas richtig funktioniert (im Browser getippt, ungetestet, aber da kann nicht viel schief gehen ;-)):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
type
  TExampleMessageEvent = procedure(Sender: TObject; AMsg: string); of object;

  TExample = class(TThread)
  private
    FOnMessage: TExampleMessageEvent;
    FCurrentMessage: string;
    procedure SyncSendTextMessage();
    procedure SendTextMessage(AMsg: string);
  protected
    procedure Execute(); override;
  public
    constructor Create(AOnMessage: TExampleMessageEvent); reintroduce;
  end;

implementation

constructor TExample.Create(AOnMessage: TExampleMessageEvent);
begin
  FOnMessage := AOnMessage;
  inherited Create(False);
end;

procedure TExample.SyncSendTextMessage();
begin
  if Assigned(FOnMessage) then
    FOnMessage(FCurrentMessage);
end;

procedure TExample.SendTextMessage(AMsg: string);
begin
  FCurrentMessage := AMsg;
  Synchronize(SyncSendTextMessage);
end;

procedure TExample.Execute();
begin
  SendTextMessage('Test');
end;
Auf diese Weise kannst du in Execute einfach die Methode SendTextMessage aufrufen, die dann mit dem Hauptthread synchronisiert das Event auslöst.

Durch die Übergabe des Eventhandlers im Konstruktor muss der Thread nicht pausiert gestartet werden. Das kann Probleme machen. Insbesondere, wenn du das in Verbindung mit FreeOnTerminate nutzt.


Flamefire - Sa 23.10.10 21:34

Was soll das?

Delphi-Quelltext
1:
if Assigned(PrintLine) then PrintLine(nil);                    


Und guck mal nach, was CreateThread macht. Warum erstellst du nicht eine neue Ableitung von TThread, was du dann erzeugst? Wenn schon OOP dann durchgängig ;-)

Und warum die AV (vermutlich) zuschlägt: Du rufst CreateThread mit TServerthread.xxx auf. TServerthread ist das Objekt. Keine Instanz. Demzufolge greift der dann auf falschen Speicherbereich zu.

Ansonten: Debug das doch mal durch und guck, wo der fehler kommt.