AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Threads und Eventhandler

Ein Thema von Codehunter · begonnen am 10. Mär 2019 · letzter Beitrag vom 11. Mär 2019
Antwort Antwort
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#1

Threads und Eventhandler

  Alt 10. Mär 2019, 18:45
Hallo!

Ich mache gerade meine ersten Schritte in Multithreading und da klemmt es gerade dabei, Eventhandler richtig anzusprechen. Hier ein stark vereinfachtes Testprogramm, dass das Problem verdeutlichen soll. Soweit ich das verstehe hat der Thread trotz EnterCriticalSection keinen Zugriff auf die Eventhandler-Methodenzeiger der Instanz von TmyClass. Nur warum verstehe ich gerade nicht so recht. Da wäre ich für ein paar Tips dankbar.

Um eine Diskussion gleich zu vermeiden: Ich verwende NOCH kein TThread weil das hier auf einem Demoprogramm aufbaut an dem ich mich erstmal orientieren will. Daher bitte keine "Mit TThread wär das nicht passiert"-Diskussion Wenn ich mal sicherer bin im Umgang mit Threads, dann mache ich auch eigene Konstruktionen in der Art.

Stürmische Grüße
Cody

Delphi-Quellcode:
unit Test;

interface

uses
  System.Classes, Vcl.Controls, Winapi.Windows;

type
  TmyClass = class(TObject)
  private
    FOnFailed: TNotifyEvent;
    FOnStarted: TNotifyEvent;
  protected
    procedure DoFailed;
    procedure DoStarted;
  public
    constructor Create;
    destructor Destroy; override;

    procedure Produce;

    property OnFailed: TNotifyEvent read FOnFailed write FOnFailed;
    property OnStarted: TNotifyEvent read FOnStarted write FOnStarted;
  end;
  
  TForm1 = class(TForm)
   procedure DoOnFailed(Sender: TObject);
   procedure DoOnStarted(Sender: TObject);
   procedure Form1Create(Sender: TObject);
   procedure Form1Destroy(Sender: TObject);
   procedure Button1Click(Sender: TObject);
  end;

var
  FThreadId: DWord;

implementation

uses
  System.SysUtils;

var
  CS: TRTLCriticalSection;
  myClass: TmyClass;
  
{ TmyClass }

constructor TmyClass.Create;
begin
  FStreamHandle := 0;
  FThreadId := 0;
end;

destructor TmyClass.Destroy;
begin
  { .. }
  inherited;
end;

procedure TmyClass.DoFailed;
begin
  if Assigned(FOnFailed) then begin // <-- FOnFailed = NIL **WARUM??**
    FOnFailed(Self);
  end;
end;

procedure TmyClass.DoStarted;
begin
  if Assigned(FOnStarted) then begin // <-- FOnStarted = NIL **WARUM??**
    FOnStarted(Self);
  end;
end;

procedure TmyClass.Produce;
var
  Dummy: Cardinal;
  Func: TThreadFunc;
  Status: Boolean;

  function _ThreadFunc: Integer;
  begin
    Result := 0;
    Status := MachIrgendwas;
    EnterCriticalSection(CS);
    try
      if Status then begin
        DoStarted;
      end else begin
        DoFailed;
      end;
    finally
      LeaveCriticalSection(CS);
    end;
    FThreadId := 0;
  end;

begin
  if FThreadId = 0 then begin
    FThreadId := BeginThread(nil, 0, @_ThreadFunc, Nil, 0, Dummy);
  end;
end;

{ TForm1 }

procedure Form1Create(Sender: TObject);
begin
  myClass := TmyClass.Create;
  myClass.OnFailed := DoOnFailed;
  myClass.OnStarted := DoOnStarted;
end;

procedure Form1Destroy(Sender: TObject);
begin
  FreeAndNil(myClass);
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  myClass.Produce;
end;

initialization

  InitializeCriticalSection(CS);

finalization

  DeleteCriticalSection(CS);

end.
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#2

AW: Threads und Eventhandler

  Alt 10. Mär 2019, 22:03
Deine _ThreadFunc ist eine lokale Funktion und keine TThreadFunc wie von BeginThread erwartet. Die Notwendigkeit des @-Operators um den Compiler zu besänftigen sollten schon ein Warnsignal gewesen sein, daß das vielleicht nicht ganz richtig sein könnte.
Delphi-Quellcode:
type
  TThreadFunc = function(Parameter: Pointer): Integer;

...
function BeginThread(SecurityAttributes: Pointer; StackSize: LongWord;
  ThreadFunc: TThreadFunc; Parameter: Pointer; CreationFlags: LongWord;
  var ThreadId: TThreadID): THandle;
Du musst also eine globale Funktion mit dieser Signatur übergeben. In dem Parameter könntest du den Pointer auf die Objekt-Instanz mitgeben, womit du dann auf DoStarted und DoFailed zugreifen könntest (bei geeigneter Sichtbarkeit). Leider bleibt dir der Zugriff auf die lokale Variable Status aber trotzdem verwehrt. Das ist aber auch gut so, da diese ja nach dem Verlassen von Produce auch nicht mehr existiert (und dann läuft dein Thread vermutlich noch).

Ich verstehe aber wirklich nicht, warum du den definitiv schwierigsten Weg wählst, um dich mit Threading zu beschäftigen, anstatt eine wenigstens halbwegs brauchbare fertige Kapselung zu verwenden. Das obige Problem ist eine direkte Folge dieser Herangehensweise. Wollte man das auch rein mit Delphi Bordmitteln erledigen, wären Anonyme Methoden und TThread oder TTask die bessere Wahl. Ist mir auch egal, ob du das nun hören willst oder nicht.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Codehunter
Codehunter

Registriert seit: 3. Jun 2003
Ort: Thüringen
2.272 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Threads und Eventhandler

  Alt 10. Mär 2019, 23:26
Wenn man schon auf die Nase fällt, dann wenigstens mit ordentlich Anlauf

Wie gesagt, das basiert auf einer (für meine Einsteiger-Verhältnisse) relativ komplexen Demo. Diese wurde offensichtlich für C++ gestrickt und dann quasi 1:1 für Delphi angepasst.

Ich habs jetzt auf TThread umgestrickt. Dort habe ich aber ähnliche Probleme. Variablen, die im Interface-Private des TThread-Objektes definiert sind, ändern sich völlig willkürlich. Deklariere ich sie Unit-global im Interface-Teil, dann funktioniert es, obwohl ich KEIN CriticalSection verwende (was ich eigentlich erwartet hätte dass dann umso mehr Probleme auftauchen müssten).

Threadprogrammierung ist schon sehr verwirrend ^^ Ein andermal mehr, morgen ist wieder Arbeit angesagt...
Ich mache grundsätzlich keine Screenshots. Schießen auf Bildschirme gibt nämlich hässliche Pixelfehler und schadet der Gesundheit vom Kollegen gegenüber. I und E zu vertauschen hätte den selben negativen Effekt, würde aber eher dem Betriebsklima schaden
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Threads und Eventhandler

  Alt 11. Mär 2019, 08:08
aus den slides meines vortrags auf den delphi-tagen 2013:

Zitat von danny thorpe:
new programmers are drawn to multithreading like moths to flame,
with similar results.
( ͡° ͜ʖ ͡°)
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
672 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: Threads und Eventhandler

  Alt 11. Mär 2019, 13:10
Wenn man schon auf die Nase fällt, dann wenigstens mit ordentlich Anlauf

Wie gesagt, das basiert auf einer (für meine Einsteiger-Verhältnisse) relativ komplexen Demo. Diese wurde offensichtlich für C++ gestrickt und dann quasi 1:1 für Delphi angepasst.

Ich habs jetzt auf TThread umgestrickt. Dort habe ich aber ähnliche Probleme. Variablen, die im Interface-Private des TThread-Objektes definiert sind, ändern sich völlig willkürlich. Deklariere ich sie Unit-global im Interface-Teil, dann funktioniert es, obwohl ich KEIN CriticalSection verwende (was ich eigentlich erwartet hätte dass dann umso mehr Probleme auftauchen müssten).

Threadprogrammierung ist schon sehr verwirrend ^^ Ein andermal mehr, morgen ist wieder Arbeit angesagt...
Man braucht halt einen anderen mindset als für die klassische RAD-"Programmierung". Wenn Du einigermaßen Fit in Englisch bist lies Dir bei Gelegenheit mal das hier durch: http://sklobovsky.nstemp.com/communi...threadmare.htm
Peter Below
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:56 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz