![]() |
AW: Synchronize mit Argumenten
Danke Uwe, ich hoffe ich habe es richtig verstanden:
Delphi-Quellcode:
Korrekturvorschläge willkommen....
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. |
AW: Synchronize mit Argumenten
Also auch mit den Änderungen sieht die Ausgabe bei mir so aus:
Zitat:
|
AW: Synchronize mit Argumenten
bei mir so, XE Pro
Code:
mhhhhhhh.....:gruebel:
Value: 1
Value: 2 Value: 3 Value: 4 Value: 5 Value: 6 Value: 7 Value: 8 Value: 9 Value: 10 vielleicht können Uwe oder Sir Rufo uns nochmals auf die Sprünge helfen. |
AW: Synchronize mit Argumenten
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. |
AW: Synchronize mit Argumenten
Zitat:
Seit wann kann Delphi 5 mit Generics umgehen? |
AW: Synchronize mit Argumenten
Zitat:
|
AW: Synchronize mit Argumenten
Also wie das Delphi 5 dahinkommt kann ich mir auch nicht erklären :shock:
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, |
AW: Synchronize mit Argumenten
nochmals Danke an Uwe und Sir Rufo
|
AW: Synchronize mit Argumenten
Liste der Anhänge anzeigen (Anzahl: 2)
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. |
AW: Synchronize mit Argumenten
So, der Code funktioniert :bounce1:
Jetzt muss ich nur noch das Beispiel von Sir Rufo komplett nachvollziehen :) Vielen Dank an Alle :thumb: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:24 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