AGB  ·  Datenschutz  ·  Impressum  







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

Update-Vorgang in einen Thread auslagern

Ein Thema von mm1256 · begonnen am 18. Dez 2014 · letzter Beitrag vom 22. Dez 2014
Antwort Antwort
Seite 1 von 2  1 2      
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#1

AW: Update-Vorgang in einen Thread auslagern

  Alt 18. Dez 2014, 16:56
Aber du möchtest es ja nicht hören ...
Nein, der Eindruck täuscht, das stimmt so wirklich nicht. Wenn ich so beratungsresistent wäre, dann würde ich (respektive meine SW bzw. Firma) anders da stehen. Die Frage ist doch anders herum die, warum ich meine eigene Installationsroutine verwende, und nicht Inno oder Installshield oder....sonst was. Das hatte ich schon. Bin damit auch glücklich gewesen, bis ich an den Punkt kam, wo es nicht mehr weiter ging. Wo diese Installationsprogramme einfach versagten, wo ich zwar Erweiterungen Plugins usw. in die Installation einbauen kann, um spezielle Aufgaben zu erledigen, aber dann kann ich den Rest auch gleich erledigen. Da geht es um mehr als nur eine SW zu installieren und sie über's WEB upzudaten.

Ich möchte dich/euch damit nicht langweilen, aber was da (an dem Installationsprogramm) alles dran hängt, das ist mit keinem Standard-Tool wie Inno & Co lösbar. Wenn es dich/euch interessiert, dann bin ich sehr gerne bereit mal einen Einblick geben, was da alles drin und dran steckt. Dann machen wir woanders (beispielsweise unter "Sonstige Werkzeuge") einen neuen Thread dafür auf.

Weil das aber nicht Bestandteil meines Problems ist, wollte ich "alternative Vorschläge" vermeiden. Diese führen in der Regel zu Diskussionen die in der Sache selber nicht weiterbringen. Dafür gibt es hier und in nahezu jedem größeren Internetforum endlose Beispiele.
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  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
 
#2

AW: Update-Vorgang in einen Thread auslagern

  Alt 18. Dez 2014, 17:06
Möglicherweise bist du nicht beratungsresistent, aber dir fehlt es gerade an Fantasie

Mit InnoSetup kann ich mir wunderbar etwas zusammenbauen, was mir aus dem Internet etwas lädt und installiert/ausführt. Ist das auf bestimmte Sachen beschränkt? Nö, muss ja nur etwas ausführbares sein. Also ich könnte mein eigenes Installationsprogramm laden/nachladen wenn nicht aktuell und ausführen. Ja, das ist möglich.

Did you get the point?
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
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
640 Beiträge
 
Delphi 10.1 Berlin Professional
 
#3

AW: Update-Vorgang in einen Thread auslagern

  Alt 18. Dez 2014, 17:14
Hallo Andreas,

was du ansprichst sind genau die Dinge, von denen ich zu wenig bis gar keine Ahnung bzw. Praxis habe. Das Installationsprogramm benutzt Units die globale Ressourcen bereitstellen, z.B. die Registry-Einträge die in einem Rutsch beim Programmstart eingelesen werden, und wenn das Programm geschlossen wird, wieder in einem Rutsch zurück geschrieben werden. Das minimiert Registry-Zugriffe. Das Updateprogramm greift auch auf diese globalen Strukturen zu. Also müsste man da "vermutlich" mit Critical Sections arbeiten. Da das aber insgesamt über einen Zeitraum von mehreren Minuten gehen kann, und Critical Sections eher kurz gehalten werden sollen, wird es wieder (zumindest für mich) komplizierter bzw. komplexer, als es auf Anhieb aussieht.

Darum war der ursprüngliche Ansatz (siehe Code) der, dass ich die ganze Form und deren Routinen in den Thread hinein packe. Was ich aber lt. Mavarik nicht tun sollte.

Mich beschleicht langsam der Gedanke, dass ich mit einer separaten DLL, deren update-ausführende Routine ich in einem Thread lade, dem Ziel näher komme. Dann habe ich zwar keine Synchronisation, aber weniger (Speicher-)Probleme, und ich weiß am Ende der Installation auch, ob der Download läuft oder nicht. Wäre das nicht eine Alternative?

@Sir Rufo
Zitat:
Möglicherweise bist du nicht beratungsresistent, aber dir fehlt es gerade an Fantasie
Na gut, dann habe ich also keine Fantasie. Damit kann ich leben, und du darfst weiterhin mit Inno glücklich sein. Was wollen wir denn mehr?
Gruss Otto
Wenn du mit Gott reden willst, dann bete.
Wenn du ihn treffen willst, schreib bei Tempo 220 eine SMS
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#4

AW: Update-Vorgang in einen Thread auslagern

  Alt 19. Dez 2014, 07:32
Die Kommunikation zwischen Threads und der Außenwelt geschieht über synchronisierte Events und geschützte Properties.

Der Thread ackert also im Hintergrund, möchte aber, das sein innerer Zustand (Was macht er gerade? Wie weit ist er?) in einer Form sichtbar ist.

Fein. Dann unterhalten die sich eben, aber nicht direkt, bitte. Das ist praktisch, weil so eine Form auch gut für andere Threads verwendet werden kann und andererseits so ein Thread auch mit einer anderen Form reden kann (oder mit gar keiner, sollte ihm schnurz sein).

Es bieten sich zum Unterhalten Events oder Interfaces an. Beides muss aber synchronisiert werden, d.h. Thread und Außenwelt laufen ja in unterschiedlichen Threads und die VCL ist nicht threadsafe, d.h. alles, was mit der VCL geschieht, muss im Hauptthread gemacht werden.

Nehmen wir mal folgenden Thread;
Delphi-Quellcode:
Procedure TMyThread.Execute;
Begin
  ShowProgressBar();
  MaxSteps := 1000;
  For i:=1 to MaxSteps do begin
     Self.Progress := I;
     UpdateProgressBar();
     DoSomething();
  end;
  HideProgressBar();
End;
Die fraglichen Methoden sind also 'ShowProgressBar', 'UpdateProgressBar' und 'HideProgressBar'.
In jedem Fall müssen die erst einmal per 'Synchronize' (oder 'Queue') aufgerufen werden, denn diese beiden Methoden sorgen dafür, das die Aufrufe im Kontext des VCL-Threads durchgeführt werden.
Also:
Delphi-Quellcode:
Procedure TMyThread.Execute;
Begin
  Synchronize(ShowProgressBar);
  MaxSteps := 1000;
  For i:=1 to MaxSteps do begin
     Self.Progress := I;
     Synchronize(UpdateProgressBar);
     DoSomething();
  end;
  Synchronize(HideProgressBar);
End;
Ok. Nun gibt es (mindestens) zwei Ansätze, wie die konkrete Kommunikation mit einem Formular aussehen kann.
1. Mit Events. Der Thread deklariert drei Eventhandler ,'OnShowProgressBar', 'OnHideProgressBar' und 'OnUpdateProgressBar' (geht auch mit einem Event, aber egal). Das Formular meldet sich auf die Events an und führt die VCL-Änderungen (Progressbar zeigen, verbergen, updaten) aus. So ungefähr
Delphi-Quellcode:
Type
  TMyThread = Class...
  public
     OnShowProgressBar : TNotifyEvent Read FOnShowProgressBar Write FOnShowProgressBar;
     OnHideProgressBar : TNotifyEvent Read FOnHideProgressBar Write FOnHideProgressBar ;
     ...
   end;

Procedure TMyThread.ShowProgressbar;
Begin
  if Assigned (FOnShowProgressBar) Then
     FOnShowProgressBar(Self);
End;
...

Procedure TMyForm.StartThread;
Begin
  FmyThread := TmyThread.Create;
  FmyThread.OnShowProgressBar := ShowProgressBar;
  FmyThread.OnHideProgressBar := HideProgressBar;
...
End;

Procedure TMyForm.ShowProgressBar (Sender : TObject);
Begin
  Progressbar.Visible := True;
End;
Oder mit einem Interface. Dabei erwartet der Thread eine 'View', die die drei Methoden zum Anzeigen der Progressbar bereitstellt.
Delphi-Quellcode:
Type
  IProgessBar = interface
    procedure ShowProgressBar;
    Procedure HideProgressBar;
    Procedure UpdateProgressBar (Position, Total : Integer);
  End;

  TMyThread = class (TThread)
    FProgess : IProgressBar;
  public
    Constructor Create (aProgress : IProgress);
  End;

...
Procedure TMyThread.ShowProgressBar;
Begin
  if Assigned (FProgress) then FProgess.ShowProgressBar;
End;

Procedure TMyThread.UpdateProgressBar;
Begin
  if Assigned (FProgress) then FProgess.UpdateProgressBar (Self.Position, Self.Total);
End;
....

Type
  TMyForm = Class (TForm, IProgress)
  ...
    Procedure ShowProgressBar;
    Procedure HideProgressBar;
    Procedure UpdateProgressBar (Position, Total : Integer);
End;
Das geht alles viel einfacher und besser, aber das Prinzip sollte klar sein. Standardpattern bei Delphi sind die Events. In anderen Programmiersprachen eher die Interfaces (Java kennt z.B. gar keine Delegaten).
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.435 Beiträge
 
Delphi 10.4 Sydney
 
#5

AW: Update-Vorgang in einen Thread auslagern

  Alt 19. Dez 2014, 09:30
Eigentlich ist das ein Fall für den asynchronen Prozeduraufruf.
Ältere Delphi-Versionen unterstützen das noch nicht.

In jedem Fall muss der Hauptthread die Ereignisse selbst auslösen.

A) Der Thread sendet Informationen über den Fortschritt mit Postmessage als Botschaft an ein Fenster, eine Komponente verarbeitet die Nachrichten und löst die Ereignisse aus.
Es ist aber nicht zu 100% sichergestellt, das wirklich alle Nachrichten auch den Empfänger erreichen, insbesondere wenn sehr viele Nachrichten in kurzer Zeit anfallen.

B) Der Thread legt Informationen über den aktuellen Progressstatus in einem geschützten Record ab, der Hauptthread prüft diesen Record periodisch (OnIDLE der Anwendung oder Timer).
Dabei können aber auch einzelne Schritte übersprungen werden, insbesondere wenn der Thread sehr schnell arbeitet.

C) Der Thread legt jede Ereignis z.B. als Objekt mit allen Informationen in einer geschützten Liste ab, der Hauptthread prüft die Liste periodisch (OnIDLE der Anwendung oder Timer).
Der Aufwand ist wahrscheinlich größer, das scheint aber die sicherste Variante zu sein.
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#6

AW: Update-Vorgang in einen Thread auslagern

  Alt 19. Dez 2014, 09:34
Na, asynchron muss das Update der Progressbar hier nun doch nicht sein. Besser wäre es natürlich, aber es geht auch so.

Bei zeitkritischen Threads, die ihre Zeit nicht mit dem Update einer UI verplempern wollen, ist das natürlich anzuraten (wobei dann ein Timer in der UI noch einfacher umzusetzen ist. EDIT: Ach, das ist ja deine Antwort 'B').

Geändert von Dejan Vu (19. Dez 2014 um 09:53 Uhr)
  Mit Zitat antworten Zitat
TakkaTukka

Registriert seit: 20. Dez 2014
1 Beiträge
 
#7

AW: Update-Vorgang in einen Thread auslagern

  Alt 20. Dez 2014, 10:44
Hallo !

Zitat:
1. Mit Events. Der Thread deklariert drei Eventhandler ,'OnShowProgressBar', 'OnHideProgressBar' und 'OnUpdateProgressBar' (geht auch mit einem Event, aber egal). Das Formular meldet sich auf die Events an und führt die VCL-Änderungen (Progressbar zeigen, verbergen, updaten) aus.
Hierzu habe ich eine Frage:
Wie muss das in der Form1 dann aussehen (komplette Deklaration), ich meine damit durch den Thread ein Event in Form1 oder Form2, .... ausgelöst wird, das ist mir vollkommen unklar ?
Ich denke damit kann man dann an mehreren Stellen im Programm auf Änderungen reagieren oder (ich denke hier z.B. an die Umstellung des Währungsformats, der Nachkommastellen, ....) ?
  Mit Zitat antworten Zitat
Benutzerbild von Mavarik
Mavarik

Registriert seit: 9. Feb 2006
Ort: Stolberg (Rhld)
4.130 Beiträge
 
Delphi 10.3 Rio
 
#8

AW: Update-Vorgang in einen Thread auslagern

  Alt 20. Dez 2014, 11:05
Das mit dem Interface sieht natürlich klasse im Source aus...

Aber warum sendest Du nicht einfach aus dem Thread eine User-Message über Windows und schon sparst Du Dir das Syncronize!

Delphi-Quellcode:
Const
         WM_PShow = WM_User + 400;
         WM_PHide = WM_USer + 401;
         WM_PUpdate = WM_USer + 402;

type
         TMyForm = class(TForm)
           private
             procedure WMShowPBar(var Msg:Tmessage); message WM_PShow;
             procedure WMHidePBar(var Msg:Tmessage); message WM_PHide;
             procedure WMUpdatePBar(var Msg:Tmessage); message WM_PUpdate;
         end;
Für Update einfach im WParam 0..100% übergeben und fertig.

Mavarik
  Mit Zitat antworten Zitat
QuickAndDirty

Registriert seit: 13. Jan 2004
Ort: Hamm(Westf)
1.889 Beiträge
 
Delphi 12 Athens
 
#9

AW: Update-Vorgang in einen Thread auslagern

  Alt 20. Dez 2014, 12:34
Mich beschleicht langsam der Gedanke, dass ich mit einer separaten DLL, deren update-ausführende Routine ich in einem Thread lade, dem Ziel näher komme. Dann habe ich zwar keine Synchronisation, aber weniger (Speicher-)Probleme, und ich weiß am Ende der Installation auch, ob der Download läuft oder nicht. Wäre das nicht eine Alternative?
Das Problem ist ja, wenn es dann ein sehr langer download ist, weil z.B. gerade viel Bandbreite beim kunden für anderen Kram draufgeht. Wie oft haben selbst wir gedacht ein programm sei eingefroren, blos weil es keine Fortschrittsanzeige hat?

Es mag dich in keiner weise beeinflussen, aber ich finde es nicht notwendig parrallel updates runterzuladen. Ich mag alles schön der reihe nach. Es ist nur ein Setu. So oft macht man das nicht.

Wofür brachst du zum Starten eines downloads die Aufmerksamkeit des Benutzers?
Damit er sich auf einem Proxyanmeldet fals es sowas beim Kunden gibt?
Ich habe as Problem noch nicht vollständig erkannt dass du gedenkst mit einem parallel laufenden Download lösen zu wollen.
Man kann solche Downloads auf jeden Fall auch einfach in einem eigenen Prozess machen. Dann erübrigt sich die Thread-Problematik.
Andreas
Monads? Wtf are Monads?
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#10

AW: Update-Vorgang in einen Thread auslagern

  Alt 20. Dez 2014, 14:35
Mir ist es ein Rätsel, wieso man den Download nicht einfach in einen kleinen Thread packt und mit einer der vier vorgestellten Methoden im Formular rummalt. Das kann doch nun jeder. Oder hab ich etwas verpasst?
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 23:45 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