| Autor |
Beitrag |
sahib
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: So 03.07.05 23:45
Moin.
Ich habe ein Hauptprogramm (Form1) und ein Anzeigefenster (Form2). Bevor in Form1 Daten verarbeitet werden, zeige ich Form2 (fsStayOnTop) an. Dort aktualisiere ich von Form1 aus einen Fortschrittsbalken (UpdateRate: 10ms). Das klappt. Aber gleichzeitig die Caption zu ändern, das klappt nicht.
Woran könnte das liegen?
Christian
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 04.07.05 06:33
Versuch mal, ob ein explizites Form2.Update; funktioniert. Manchmal hat sich die VCL etwas ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
sahib 
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Mo 04.07.05 08:14
Hallo Benny.
Vielen Dank für Deine Antwort. Leider hat das auch nichts gebracht. Ich verliere nochmal ein paar Worte dazu. Die ganzen durchzuführenden Rechnungen werden in einer Schleife durchlaufen. Am Anfang aktualisierte ich ProgressBar und Caption innerhalb der Schleife und das funktionierte. Dann habe ich das entkoppelt und aktualisiere die Anzeige in einem weiteren Thread.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| function MyThread(p: Pointer): Integer; begin repeat TGauge(p).Progress := Form1.Process; Form2.Caption := Format('%u%% fertig', [Form1.OverallProcess]); Form2.Update; Application.ProcessMessages; Sleep(Form1.UpdateRate) until False end;
hThread := BeginThread(nil, 0, @MyThread, Form2.Gauge2, 0, ID); |
Ich habe mit der UpdateRate gespielt, dachte, dass die VCL nicht hinterherkäme, aber das war es auch nicht. Auf die Threadlösung habe ich zurückgegriffen, damit der User selbst die UpdateRate einstellen kann (macht das eigentlich Sinn? - fragte er sich selber). Weiterhin nutze ich den Thread, um auch andere ProgressBars zu bedienen, die alle nacheinander angesprochen werden. Die Rechnung habe ich nicht ausgelagert, weil der Nutzer mit dem Programm während der Rechnung eh nicht weiterarbeiten darf.
Christian
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 04.07.05 11:36
Gut, bei Threads sind mit der VCL schon Probleme vorprogrammiert. Du musst jegliche Zugriffe auf Properties der VCL innerhalb eines Threads synchronisieren, sofern Du solche Effekte vermeiden willst. Schau Dir mal TThread.Synchronize an und implementiere darin dein Update der Form-Caption. Ein unsynchronisiertes Application.ProcessMessages innerhalb eines Threads kann sogar tödlich wirken ...
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
sahib 
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Mo 04.07.05 12:51
Danke für den Hinweis, Benny. Bisher ging soweit immer alles gut.
Aber was muss ich denn jetzt synchronisieren? Ich starte meinen Thread über
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| var hThread: THandle; ID: Cardinal;
hThread := BeginThread(nil, 0, @MyThread, Form2.Gauge2, 0, ID); |
und beende ihn via
Delphi-Quelltext 1:
| TerminateThread(hThread, ID); |
Sehe ich das richtig, dass ich den Inhalt der Prozedur MyThread in eine andere Prozedur schieben muss, damit ich aus MyThread heraus ein Synchronize(NeueProzedur) ausführen kann?
Christian
|
|
BenBE
      
Beiträge: 8721
Erhaltene Danke: 191
Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
|
Verfasst: Mo 04.07.05 13:00
Du erzeugst eine Abgeleitete Klasse TDeinThread.
Dort überschreibst Du die Procedure Execute mit deinem Source.
Außerdem deklarierst Du eine weitere Prozedure UpdateForm, in der Du die ganzen Zugriffe auf VCL-Controls der Anwendung auslagerst (zumindest die Aktualisierung der Caption).
Danach den Thread mit TDeinThread.Create erzeugen.
_________________ Anyone who is capable of being elected president should on no account be allowed to do the job.
Ich code EdgeMonkey - In dubio pro Setting.
|
|
sahib 
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Mo 04.07.05 14:12
Danke, Benny.
Nach Studium von Lucky's Tutorial habe ich meine Applikation umgeschrieben. Das gute: es läuft wie zuvor auch ohne Absturz. Aber die Caption wird nach wie vor nicht angezeigt und der Fortschrittsbalken schreitet nun auch nicht mehr voran. Wird aber alles korrekt aufgerufen.
Ich werde noch ein wenig weite studieren...
Christian
|
|
sahib 
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Di 02.08.05 10:11
Hallo.
Das Studium war wohl so erfolgreich nicht. Habe mich letzte Nacht nochmal daran gewagt, das Programm vereinfacht und in den Anhang gesteckt.
Was wird gemacht (soll gemacht werden)? Das Hauptprogramm besteht aus einer Schleife, die fortwährend den Schleifenzähler in ListBox1 schreibt. Jede Sekunde soll dann der letzte Wert der ersten ListBox in die zweite übertragen werden.
Aber irgendwo steckt da in dem Code ein Fehler, den ich nicht sehe. Später soll es wie zuvor laufen: Hauptprogramm rechnet und in einer zweiten Form sollen Zwischenergebnisse dargestellt werden.
Es wäre nett, wenn mich jemand mal auf den Fehler stoßen könnte.
Danke,
Christian
Einloggen, um Attachments anzusehen!
|
|
sahib 
      
Beiträge: 117
Win 2000 SP4+
Delphi 5 Prof.
|
Verfasst: Di 02.08.05 16:03
Ok, scheinbar habe ich es doch noch geschafft. Zumindest dieses Beispiel läuft nun. Ich habe einfach die Hauptprogrammschleife und das Erzeugen/Starten des Update-Threads voneinander getrennt. Warum das aber vorher nicht auch lief, ist mir ein Rätsel.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24:
| procedure TForm1.Button1Click(Sender: TObject); begin UpdateThread := TUpdateThread.Create(True); UpdateThread.Priority := tpIdle; UpdateThread.FreeOnTerminate := True; UpdateThread.Resume; end;
procedure TForm1.Button2Click(Sender: TObject); begin Beenden := True; UpdateThread.Terminate end;
procedure TForm1.FormActivate(Sender: TObject); var i: LongWord; begin repeat ListBox1.Items.Add(IntToStr(i)); Application.ProcessMessages; inc(i) until Beenden end; |
Auf ein baldiges Wochenende,
Christian
|
|
|