AGB  ·  Datenschutz  ·  Impressum  







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

Synchronize mit Argumenten

Ein Thema von Viktorii · begonnen am 9. Feb 2011 · letzter Beitrag vom 10. Aug 2011
Antwort Antwort
Seite 4 von 5   « Erste     234 5      
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#31

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 14:05
Danke Uwe, ich hoffe ich habe es richtig verstanden:
Delphi-Quellcode:
unit Unit2;

interface

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



type
  TProgress = procedure(const Value: integer) of object;

type
  TMyThread = class(TThread)
  private
    FValue: Integer;
    FProgress: TProgress;
    procedure SyncProgress(Value:Integer);
  protected
    procedure Execute; override;
  public
    property Progress: TProgress write FProgress;

  end;
  TForm2 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private-Deklarationen }
    FMyThread: TMyThread;
    procedure progress(const value: Integer);
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TMyThread.Execute;
var
  i: Integer;
begin
  for i := 1 to 10 do
  begin
    FValue := i;
    SyncProgress(i);
    sleep(200);
    OutputDebugString(PWideChar('FValue: ' + IntToStr(FValue)));
  end;
end;

procedure TMyThread.SyncProgress(Value:Integer);
begin
    Queue(
    Procedure
      begin
          FProgress(Value);
      end
    );
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  Memo1.Clear;
  FMyThread := TMyThread.Create(true);
  FMyThread.Progress := progress;
  FMyThread.Resume;
end;

procedure TForm2.progress(const value: Integer);
begin
  Memo1.Lines.Add('Value: ' + IntToStr(value));
  sleep(500);
end;
end.
Korrekturvorschläge willkommen....
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#32

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 14:13
Also auch mit den Änderungen sieht die Ausgabe bei mir so aus:
Zitat:
Value: 1
Value: 3
Value: 5
Value: 8
Value: 10
Value: 10
Value: 10
Value: 10
Value: 10
Value: 10
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#33

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 14:16
bei mir so, XE Pro
Code:
Value: 1
Value: 2
Value: 3
Value: 4
Value: 5
Value: 6
Value: 7
Value: 8
Value: 9
Value: 10
mhhhhhhh.....

vielleicht können Uwe oder Sir Rufo uns nochmals auf die Sprünge helfen.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  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
 
#34

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 16:05
Der Code von Bummi in #31 ist soweit in Ordnung, bis auf ein paar Kleinigkeiten:

a) das Feld FValue kann entfallen, da es nur noch innerhalb Execute verwendet wird

b) du musst noch etwas tun, damit der Thread nicht beendet wird, bevor die Queues abgearbeitet sind. Das genaue Verhalten ist natürlich von diversen Umständen abhängig, aber bei meinem System fehlt die 10 im Memo, wenn ich das OutputDebugString auskommentiere und es kommt fast gar nichts mehr an, wenn ich das Sleep(200) auch weglasse.

Und Viktorii: Wenn es bei dir nicht geht, hast du vermutlich noch einen Fehler drin. Kann ich ohne aktuelle Sourcen aber nicht erkennen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#35

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 16:14
(Das erste mal dass ich mit Generics gearbeitet habe )


Seit wann kann Delphi 5 mit Generics umgehen?
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  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
 
#36

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 16:22
(Das erste mal dass ich mit Generics gearbeitet habe )


Seit wann kann Delphi 5 mit Generics umgehen?
Und TThread.Queue gab's damals auch noch nicht...
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#37

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 17:49
Also wie das Delphi 5 dahinkommt kann ich mir auch nicht erklären

Hab jetzt mittlerweile auch Delphi XE. Sorry für die Verwirrung.


Was den Code angeht: Kann sein dass ich da einen Bug eingebaut habe. War ein wenig zwischen Tür und Angel getestet.

Wie es aussieht habe ich vor Montag kein Delphi zur Verfügung. Werde es spätestens dann testen.

Schönes Wochenende an alle,
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#38

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 18:29
nochmals Danke an Uwe und Sir Rufo
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#39

AW: Synchronize mit Argumenten

  Alt 11. Feb 2011, 18:59
Sodele, jetzt habe ich mal einen DemoThread inkl. einer Exe zum Ausprobieren.

Mit der Exe kann man schön das Zeitverhalten von Queue und Sync beobachten (auch, dass keine Werte verloren gehen).
Für den Vergleich unter Last gibt es unten den Schalter "Arbeitstimer aktiv". Dieser simuliert eine starke Auslastung vom MainThread.

Interessant ist dabei das Verhalten von Queue und Sync zu sehen.

Den Code-Vorschlag von Uwe habe ich mal eingearbeitet (als SlowSync) und eine kleine Abwandlung (FastSync).
Das Fast und SLow kommt allerdings erst dann zum Tragen, wenn das Event für den Sync nicht zugewiesen ist,
also eigentlich kein Sync erfolgen müsste.

Der Code von Uwe führt aber immer den Sync aus => SlowSync
Mein Code führt den Sync nur aus wenn auch wirklich benötigt => FastSync

Aber ... der Zugriff auf die Prop OnInfoEvent erfolgt beim FastSync noch im ThreadKontext und muss daher entsprechend geschützt sein (siehe Getter von OnInfoEvent).

Der SlowSync kann direkt auf des Feld FOnInfoEvent zugreifen (es sei denn diese Prop würde auch von anderen Thread gelesen/beschrieben, dann muss das eh komplett mit einer CS gesichert werden)

Hier der ThreadCode (Exe und kompletter Source im Anhang):
Delphi-Quellcode:
unit uDemoThread;

interface

uses
  Classes,
  SyncObjs;

type
  TNotifyInfoEvent = procedure( const Info : string; Ticks : Cardinal ) of object;

  TThreadExecType = ( tetSlowSync, tetFastSync, tetQueue );

  TDemoThread = class( TThread )
  private
    { Private-Deklarationen }
    FEventCS : TCriticalSection;
    FOnInfoEvent : TNotifyInfoEvent;
    FExecType : TThreadExecType;
    procedure CallSlowSyncEvent( const Info : string; Ticks : Cardinal = 0 );
    procedure CallFastSyncEvent( const Info : string; Ticks : Cardinal = 0 );
    procedure CallQueueEvent( const Info : string; Ticks : Cardinal = 0 );
    function GetOnInfoEvent : TNotifyInfoEvent;
    procedure SetOnInfoEvent( const Value : TNotifyInfoEvent );
  protected
    procedure Execute; override;
  public
    constructor Create( CreateSuspended : Boolean; ExecType : TThreadExecType = tetSlowSync );
    destructor Destroy; override;
  published
    property OnInfoEvent : TNotifyInfoEvent
      read GetOnInfoEvent
      write SetOnInfoEvent;
  end;

implementation

uses
  SysUtils, Windows;

{ TDemoThread }

procedure TDemoThread.CallSlowSyncEvent( const Info : string; Ticks : Cardinal );
var
  IntTicks : Cardinal;
begin
  // Der SlowSync synchronisiert IMMER mit dem Hauptthread
  // egal, ob ein Event verknüpft ist oder nicht
  // Wenn kein Event verknüpft ist, bräuchte ja eigentlich kein Sync erfolgen
  if MainThreadID = GetCurrentThreadId
  then
    begin
      if Assigned( FOnInfoEvent )
      then
        FOnInfoEvent( Info, Ticks );
    end
  else
    begin
      IntTicks := GetTickCount;
      Synchronize( procedure begin CallSlowSyncEvent( 'via SlowSync: ' + Info, IntTicks ) end );
    end;
end;

procedure TDemoThread.CallFastSyncEvent( const Info : string; Ticks : Cardinal );
var
  IntTicks : Cardinal;
begin
  // Der Fast-Sync synchronisiert nur, wenn auch ein Event zugewiesen wurde
  // Da diese Abfrage aber noch im Thread-Kontext erfolgt, muss die
  // Eigenschaft OnInfoEvent über eine CS abgesichert werden
  if Assigned( OnInfoEvent )
  then
    if MainThreadID = GetCurrentThreadId
    then
      FOnInfoEvent( Info, Ticks )
    else
      begin
        IntTicks := GetTickCount;
        Synchronize( procedure begin CallFastSyncEvent( 'via FastSync: ' + Info, IntTicks ) end );
      end;
end;

procedure TDemoThread.CallQueueEvent( const Info : string; Ticks : Cardinal );
var
  IntTicks : Cardinal;
begin
  // Beim Queue ist es völlig wurscht, ob da nun eine Sync erfolgt oder nicht,
  // denn dieser Aufruf erfolgt eh asynchron und beschäftigt den Thread nicht weiter
  if MainThreadID = GetCurrentThreadId
  then
    begin
      if Assigned( OnInfoEvent )
      then
        FOnInfoEvent( Info, Ticks );
    end
  else
    begin
      IntTicks := GetTickCount;
      Queue( procedure begin CallQueueEvent( 'via Queue: ' + Info, IntTicks ) end );
    end;
end;

constructor TDemoThread.Create( CreateSuspended : Boolean; ExecType : TThreadExecType );
begin
  FEventCS := TCriticalSection.Create;
  FEventCS.Enter;
  try
    inherited Create( CreateSuspended );
    FExecType := ExecType;
    FreeOnTerminate := True;
  finally
    FEventCS.Leave;
  end;
end;

destructor TDemoThread.Destroy;
begin
  FEventCS.Enter;
  try

    inherited;
  finally
    FEventCS.Leave;
    FreeAndNil( FEventCS );
  end;
end;

procedure TDemoThread.Execute;
var
  idx : Integer;
  Info : string;
begin
  Sleep( 25 );
  { Thread-Code hier einfügen }
  for idx := 0 to 10 do
    begin
      Info := 'Ich bin bei ' + IntToStr( idx );
      case FExecType of
        tetSlowSync :
          CallSlowSyncEvent( Info );
        tetFastSync :
          CallFastSyncEvent( Info );
        tetQueue :
          CallQueueEvent( Info );
      end;
    end;

  // Wenn dieser "Slow"-Sync nicht gemacht wird, kann es sein,
  // dass einige Nachrichten über die Queue verloren gehen!!!!
  case FExecType of
    tetSlowSync: CallSlowSyncEvent( 'Fettich!' );
    tetFastSync: CallFastSyncEvent( 'Fettich!' );
    tetQueue: CallSlowSyncEvent( 'Fettich! (Queue)' );
  end;

end;

function TDemoThread.GetOnInfoEvent : TNotifyInfoEvent;
begin
  FEventCS.Enter;
  try
    Result := FOnInfoEvent;
  finally
    FEventCS.Leave;
  end;
end;

procedure TDemoThread.SetOnInfoEvent( const Value : TNotifyInfoEvent );
begin
  FEventCS.Enter;
  try
    FOnInfoEvent := Value;
  finally
    FEventCS.Leave;
  end;
end;

end.
Angehängte Dateien
Dateityp: zip ThreadDemo_src.zip (3,7 KB, 15x aufgerufen)
Dateityp: zip ThreadDemo_exe.zip (462,0 KB, 11x aufgerufen)
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Viktorii

Registriert seit: 19. Jul 2007
358 Beiträge
 
#40

AW: Synchronize mit Argumenten

  Alt 14. Feb 2011, 12:03
So, der Code funktioniert

Jetzt muss ich nur noch das Beispiel von Sir Rufo komplett nachvollziehen

Vielen Dank an Alle
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 4 von 5   « Erste     234 5      


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 21:47 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