Autor Beitrag
sahib
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: 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.

ausblenden 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;  // zeigt auf irgendeinen (s.u.) TGauge
    Form2.Caption := Format('%u%% fertig', [Form1.OverallProcess]);
    Form2.Update;
    Application.ProcessMessages;
    Sleep(Form1.UpdateRate)  // nur alle x ms ausführen
  until False
end;

// gestartet dann zB so
  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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: 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
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
var
  hThread: THandle;
  ID: Cardinal;

  // MyThread: siehe obige Nachricht
  hThread := BeginThread(nil, 0, @MyThread, Form2.Gauge2, 0, ID);

und beende ihn via
ausblenden 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
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 8721
Erhaltene Danke: 191

Win95, Win98SE, Win2K, WinXP
D1S, D3S, D4S, D5E, D6E, D7E, D9PE, D10E, D12P, DXEP, L0.9\FPC2.0
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: 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 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 117

Win 2000 SP4+
Delphi 5 Prof.
BeitragVerfasst: 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.


ausblenden 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;

// Beende Update-Thread
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