![]() |
DEC onProgress-Ereignis bei mehreren Threads
Folgendes: In einer Liste habe ich verschiedene Dateien zum Verschlüsseln. Für jede Datei wird jetzt ein Thread mit BeginThread gestartet. In diesem Thread wird jetzt dynamisch die Cipher-Komponente erzeugt und dem OnProgress Ereignis eine Prozedur zugewiesen. In einer zweiten Spalte eines Listview soll nur der Fortschrit separat für jede Datei angezeigt werden. Wie teile ich OnProgress jetzt mit welche Spalte er aktualisieren soll?
Ich habe kein TTHread-Object, sondern arneite mit der Windows-API. Schema:
Code:
Das "X" ist jetzt das Problem.
procedure MyProgress;
begin Listview1.Items[x],Subitems[0].Text := y%; end; function Thread begin TCipher.OnProgress := myProgress; end; |
Re: DEC onProgress-Ereignis bei mehreren Threads
Mein Lösungsversuch:
Ich vergebe beim Erstellen im Thread die Tag-Eigenschaft. In OnProgress ist sie aber immer 0. |
Re: DEC onProgress-Ereignis bei mehreren Threads
So ich habe es jetzt geschaft, aber nicht so richtig. Ich benutze jetzt ein TThread-Objekt.
Delphi-Quellcode:
Allerdings zählt er nur die letzte Datei hoch. :?
procedure BlowFishThread.EncryptBlowFish;
var BlowFish: TCipherManager; begin BlowFish := TCiphermanager.Create(nil); with BlowFish do begin try Algorithm := 'Blowfish'; InitKey(FPW, nil); OnProgress := Progress; EncodeFile(FFilename, FFilename + '.encoded'); except BlowFish.Free; FPosition := -1; exit; end; end; BlowFish.Free; end; procedure BlowFishThread.Progress; begin FPosition := Trunc(100 / Maximal * Current); Synchronize(UpLV); end; procedure BlowFishThread.Execute; var Header: TFileHeader; begin EncryptBlowFish; with Header do begin HeaderSize := sizeof(TFileHeader); sVersion := VER; sAlgo := ALGO_BLOWFISH; KeySize := 0; end; Addheader(Header, Filename + '.encoded'); end; procedure BlowFishThread.UPLV; begin Form1.UpLV(FIndex, FPosition); end; |
Re: DEC onProgress-Ereignis bei mehreren Threads
Liste der Anhänge anzeigen (Anzahl: 1)
So eine Konstruktion hilft auch nicht:
Delphi-Quellcode:
procedure BlowFishThread.Execute;
var Header: TFileHeader; begin setlength(FIndexArray, length(FIndexArray)+1); FIndexArray[length(FIndexArray)-1] := FIndex; setlength(FPositionArray, length(FPositionArray)+1); EncryptBlowFish;
Delphi-Quellcode:
procedure BlowFishThread.Progress;
var i: Integer; begin for i := 0 to length(FPositionArray)-1 do begin FPositionArray[i] := Trunc(100 / Maximal * Current); end; Synchronize(UpLV); end;
Delphi-Quellcode:
Ich habe jetzt mal das Projekt angehangen. Ob das sicher ist sei erst mal dahingestellt. benötigt wird das DEC von Hagen Reddmann.
procedure BlowFishThread.UPLV;
var i: Integer; begin for i := 0 to length(FIndexArray)-1 do begin Form1.UpLV(FIndexArray[i], FPositionArray[i]); writeln(IntToStr(FIndexArray[i])+' / '+IntToStr(FPositionArray[i])); break; end; end; |
Re: DEC onProgress-Ereignis bei mehreren Threads
Liste der Anhänge anzeigen (Anzahl: 1)
So Code etwas überarbeitet. Es geht aber immer noch nicht, so wie ich will.
|
Re: DEC onProgress-Ereignis bei mehreren Threads
Hi Luckie,
sorry für die späte Antwort, aber es gibt auch mal einen Geburtstag zu feiern. Also, es ist schon erschreckend wie du so schnell die Schwachstellen im DEC findest. OnProgress() ist ein globales Event das 1. nicht threadsafe ist und 2. global immer nur einen Verschlüsselungsprozess unterstützt. D.h. mit OnProgress() wirst du das was du willst nie hinbekommen. Vergiss es also. Verzichte auf TCipherManager/THashManager, beides sind Komponenten die ich für die DAU's coden musste, es sind Drag&Design Hilfsmittel. Nachfolgend zeige ich wie man jeden Stream mit Progress Funktionalität ausbauen kann. D.h. deine Progressbar sollte individuell zum Streaming sein, dann ist sie auch threadsafe. Desweiteren zeige ich wie man Verschlüsselt ohne TCipherManager, die Entschlüsselung bekommste damit selber hin.
Delphi-Quellcode:
Gruß Hagen
type
TStreamProgressAdapter = class(TStream) private FStream: TStream; protected procedure SetSize(NewSize: Longint); override; public constructor Create(AStream: TStream); destructor Destroy; override; function Read(var Buffer; Count: Longint): Longint; override; function Write(const Buffer; Count: Longint): Longint; override; function Seek(Offset: Longint; Origin: Word): Longint; override; procedure DoProgress(Writing: Boolean); virtual; end; procedure TStreamProgressAdapter.SetSize(NewSize: Longint); begin TStreamProgressAdapter(FStream).SetSize(NewSize); end; constructor TStreamProgressAdapter.Create(AStream: TStream); begin inherited Create; FStream := AStream; end; destructor TStreamProgressAdapter.Destroy; begin inherited Destroy; FStream.Free; end; function TStreamProgressAdapter.Read(var Buffer; Count: Longint): Longint; begin Result := FStream.Read(Buffer, Count); DoProgress(False); end; function TStreamProgressAdapter.Write(const Buffer; Count: Longint): Longint; begin Result := FStream.Write(Buffer, Count); DoProgress(False); end; function TStreamProgressAdapter.Seek(Offset: Longint; Origin: Word): Longint; begin Result := FStream.Seek(Offset, Origin); end; procedure TStreamProgressAdapter.DoProgress(Writing: Boolean); begin // hier deine Progress Funktionen einbauen end; procedure Encrypt(Stream: TStream; const Password: String; CipherClass: TCipherClass = nil); overload; begin if CipherClass = nil then CipherClass := TCipher_Blowfish; with CipherClass.Create('', nil) do try Mode := cmCTS; InitKey(Password, nil); EncodeStream(Stream, Stream, -1); finally Free; end; end; procedure Encrypt(const FileName, Password: String; CipherClass: TCipherClass = nil); overload; var Stream: TStream; begin Stream := TStreamProgressAdapter.Create(TFileStream.Create(FileName, fmOpenReadWrite or fmShareExclusive)); try Encrypt(Stream, Password, CipherClass); finally Stream.Free; end; end; procedure TestC; begin Encrypt('d:\test.bin', 'Test'); Encrypt('d:\test.bin', 'Test', TCipher_Rijndael); Encrypt('d:\test.bin', 'Test', TCipherClass(DECClassByName('IDEA', TCipher))); end; |
Re: DEC onProgress-Ereignis bei mehreren Threads
Danke. Dann habe ich es ja gerade im richtigen Moment wieder hervor geholt.
Wie komme ich in OnProgress an die Werte dran und wie weise ich das Ereignis einer Ver- / Entschlüsselung zu? |
Re: DEC onProgress-Ereignis bei mehreren Threads
Du redest jetzt von obigem TStreamProgressAdapter ?
Diese Klasse muß natürlich erweitert werden. Im .DoProgress kann man über FStream.Size und FStream.Position das Verhältniss ermittelt werden. In meinem eigene Source habe ich dies allerdings über eigene Variablen gemacht. Also im Contructor FStream.Size zwischen gespeichert. Im .Seek() .Read() und .Write() zähle ich eine eigene FPosition mit. Im .DoProgress() kann ich nun die berechnete FSize und FPosition von TStreamProgressAdapter auswerten. Dies verhindert unnötige Repositionierungen wenn man mit FStream.Position und FStream.Size arbeitet. Intern wird nämlich über Seek() die Größe des Stream ermittelt. Gruß Hagen |
Re: DEC onProgress-Ereignis bei mehreren Threads
Liste der Anhänge anzeigen (Anzahl: 1)
So. Ich habe das jetzt mal eingebaut noch ohne Threads nur zum Testen. Leider bin ich da auf ein paar Probleme gestossen.
Erst mal habe ich den von dir gepostet Code in eine Unit gesteckt und entsprechend erweitert. Du findest sie im Anhang. Dann habe ich versucht den Code anzuwenden. Habe da aber wohl noch ein paar Verständnisschwierigkeiten.
Delphi-Quellcode:
Frage: Kann es so überhaupt funktionieren? Weil wenn ich in der Schleife den ProgressAdapter gleich wieder freigebe, dann war es das ja gewesen, deswegen die drei Dedektive (???) an dieser Stelle.
procedure TForm1.btnOKClick(Sender: TObject);
var i: Integer; Filename: string; ProgressAdapter: TStreamProgressAdapter; FileStream: TFileStream; begin for i := 0 to lvFiles.Items.Count - 1 do begin Filename := lvFiles.Items.Item[i].Caption; if lvFiles.Items.Item[i].SubItems[0] = 'unverschlüsselt' then begin FileStream := TFileStream.Create(Filename, fmOpenReadWrite); try ProgressAdapter := TStreamProgressAdapter.Create(FileStream); try Encrypt(FileStream, edtPW1.Text, TCipher_Rijndael); // 156 lvFiles.Items.Item[i].SubItems[0] := FloatToStr(ProgressAdapter.Progress); finally {???} end; finally FreeAndNil(FileStream); end; end; end; end; Probleme: Zitat:
Zitat:
|
Re: DEC onProgress-Ereignis bei mehreren Threads
Einfacher, TProgressAdapter gibt den Stream den er kapselt selber frei. D.h. FileStream.Free ist in jedem Falle falsch.
Delphi-Quellcode:
D.h. der Stream den man einem TStreamProgressAdapter übergibt ist irrelevant und muß nicht mehr als variable gespeichert werden. Alle Stream-Funktionen laufen nur über den ProgressAdapter, er kapselt sozusagen vollständig ein anderes Stream Object. Der Vorteil: statt ihn nur für Progressbars zu nutzen kann er auch beim Lesen/Schreiben Prüfsummen berechnen, zusätzlich komprimieren und vwerschlüsseln. Dazu müssen nur die .Write() .Read() Methoden angepasst werden.
ProgressAdapter := TStreamProgressAdapter.Create(TFileStream.Create(FileName, Mode));
try ProgressAdapter.Read(); ProgressAdapter.Write(); finally ProgressAdapter.Free; end; Gruß Hagen |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:21 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