Autor Beitrag
Elrond
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 16.10.08 01:04 
Hallo allerseits,

ich brauche ein wenig Hilfe. Seit ein paar Wochen beschäftige ich mit mit Delphi 5. Bisher kam ich trotz Start bei Null recht gut klar, aber jetzt hänge ich fest.

Problem: Ich habe ein rechenintensives Programm geschrieben, welches ich bei Bedarf per Button abbrechen möchte, da unter gewissen Bedingungen minutenlang gerechnet und wie wild Informationen in ein StringGrid geschrieben werden.

Um auf Interrupts reagieren zu können, habe ich dafür gesorgt, dass öfters Application.ProcessMessages aufgerufen wird. Ein Abbruch-Button ist mit einer OnClick-Prozedur verbunden, aber bedauerlicherweise passiert gar nichts und ich muss das Programm dann per Task-Manager killen.

Für Ratschläge und Hilfe wäre ich außerordentlich dankbar.

Grüße

Elrond


Moderiert von user profile iconNarses: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Do 16.10.2008 um 01:30
ub60
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 764
Erhaltene Danke: 127



BeitragVerfasst: Do 16.10.08 01:21 
Mit einem Abbruch-Button eine globale Variable setzen.
In der Rechenschleife die Variable abfragen und dann gegebenenfalls Schleife verlassen.

ub60
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 16.10.08 01:28 
Alles schon probiert. Die OnClick-Prozedur macht genau das und funktioniert auch prima, solange mein Rechenmonster nicht läuft. Dann erhält die Prozedur trotz Application.ProcessMessages (wird laut Debugger regelmäßig ausgeführt) einfach nicht die Kontrolle und dann wird die globale Variable natürlich auch nicht gesetzt.

Elrond
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 16.10.08 01:31 
Moin und :welcome: im Forum!

user profile iconElrond hat folgendes geschrieben Zum zitierten Posting springen:
Alles schon probiert.
Dann wäre jetzt der Zeitpunkt für etwas Code, wie sollen wir sonst rausfinden, was da hakt? :nixweiss: ;)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Dunkel
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Do 16.10.08 01:53 
Hallo und willkommen im Forum!

Applicatin.ProcessMessages(); sollte nach Möglichkeit vermieden werden, das ist ungefähr genau so pöse wie goto und Konsorten.
Lager Deine lang andauernde Berechnung in eine Thread aus, diesen kannst Du, nach Bedarf, einfach absch(l)ießen; VCL-Zugriffe synchronisieren natürlich nicht vergessen.

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 16.10.08 02:08 
Moin!

user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
Applicatin.ProcessMessages(); sollte nach Möglichkeit vermieden werden, das ist ungefähr genau so pöse wie goto und Konsorten.
Na, wir wollen mal nicht übertreiben. :| (und nicht in eine goto-Diskussion abgleiten! :mahn:)

In einer "vernünftig" konzipierten VCL-Anwendung ist das kein Problem (die Controls müssen halt passend zum aktuellen Programm-Zustand de-/aktiviert sein!). :nixweiss: Andersrum: wenn du mit APM Probleme bekommst, hast du einen fetten Bug in deinem Ereignisverarbeitungskonzept. ;)

user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
Lager Deine lang andauernde Berechnung in eine Thread aus, diesen kannst Du, nach Bedarf, einfach absch(l)ießen; VCL-Zugriffe synchronisieren natürlich nicht vergessen.
Wenn er schon mit APM nicht klar kommt, dann wird das ja mit Threads sicher besser funktionieren... :D

@user profile iconElrond: Zeig mal deinen Code, dann sehen wir weiter. :)

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Dunkel
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 682

Mac OS X Snow Leopard
Xcode 3.1
BeitragVerfasst: Do 16.10.08 02:23 
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
In einer "vernünftig" konzipierten VCL-Anwendung ist das kein Problem {...}

VCL hin, VCL her, in einer "vernünftig" konzipierten Anwendung ist (ich habe ein wenig darüber nachgedacht, was das bedeutet) APM nicht von Nöten. Und pöse ist es trotzdem (mehrfach gefeuerte Ereignisse und Messages & Co., schwer zu debuggen ist es ebenfalls)

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Wenn er schon mit APM nicht klar kommt, dann wird das ja mit Threads sicher besser funktionieren... :D

Das hoffe ich doch... :wink:

user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
@user profile iconElrond: Zeig mal deinen Code, dann sehen wir weiter. :)

Full Ack.!

_________________
Ich streite einsam mich mit dieser Oberflächenwelt
Gutes sei ein löblich Brot von dem ich zehre - bis zum Tod [Das Ich - Im Ich]
Narses
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Administrator
Beiträge: 10183
Erhaltene Danke: 1256

W10ent
TP3 .. D7pro .. D10.2CE
BeitragVerfasst: Do 16.10.08 03:10 
Moin!

user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
VCL hin, VCL her, in einer "vernünftig" konzipierten Anwendung ist (ich habe ein wenig darüber nachgedacht, was das bedeutet) APM nicht von Nöten.
Ich habe nicht bestritten, das APM (normalerweise) unnötig ist. ;) vielleicht hast du also doch noch nicht lange genug drüber nachgedacht? *g*

user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
Und pöse ist es trotzdem (mehrfach gefeuerte Ereignisse und Messages & Co., schwer zu debuggen ist es ebenfalls)
Es ist weder "pöse", noch wird wird da was mehrfach gefeuert, wenn man eine VCL-konforme Anwendung hat. :nixweiss: Glaubst du nicht? Dann beweise das Gegenteil (Code!). :) Ich wiederhole mich gerne, aber begrenzt: wenn du deine Anwendung/Controls z.B. über einen Zustand im Griff hast, dann spielt es keine Rolle, ob du APM aufrufst :arrow: es wird dann einfach keine Probleme geben, wenn man es trotzdem aufruft. :P

user profile iconDunkel hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconNarses hat folgendes geschrieben Zum zitierten Posting springen:
Wenn er schon mit APM nicht klar kommt, dann wird das ja mit Threads sicher besser funktionieren... :D

Das hoffe ich doch... :wink:
Das hoffe ich zwar auch :angel: aber die Wahrscheinlichkeit ist gegen uns... :rofl:

cu
Narses

_________________
There are 10 types of people - those who understand binary and those who don´t.
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 16.10.08 15:47 
Hallo Leute,

erstmal herzlichen Dank für eure Kommentare. Bedenkt bitte, dass ich Delphi vor 3 Wochen zum ersten mal gesehen habe und ich eigentlich ganz glücklich bin, dass bisher alle Applikationen super laufen ("Wenn er schon mit APM nicht klar kommt, dann wird das ja mit Threads sicher besser funktionieren..." :roll: ).

Auch dieses Programm läuft eigentlich prima, ich frage mich halt nur, warum die OnClick-Prozeduren die Kontrolle nicht bekommen, wenn ich erstmal in der Rechenschleife bin.

Da APM ja dafür sorgt, dass aufgelaufene Messages abgearbeitet werden (und dazu zählen eben auch Dinge wie Mausclicks oder Keypress), scheint das eigentlich kein schlechter Gedanke zu sein. Im Debugging Modus funktioniert alles planmäßig.

Der interessanteste Hinweis scheint mir der von Dunkel zu sein: "VCL-Zugriffe synchronisieren natürlich nicht vergessen." Was genau meinst Du damit?

P.S. Den Code hier reinzugeben bringt angesichts der Größe wenig. Aber prinzipiell sieht das Ding so aus:

Ursprünglich gab es eine simple Schleife:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
procedure loese_Aufgabe;
begin
  while (b_s_1(Feld) > 0do
  begin
   einzelschritt;
   anzeigen(Feld)
  end;
end;


...und die läuft unter Umständen etliche Minuten. Also habe ich das Ding erweitert.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
procedure loese_Aufgabe;
begin
  while (b_s_1(Feld) > 0do
  begin
   einzelschritt;
   anzeigen(Feld);
   Application.ProcessMessages;
   if Abbr then exit;
  end;
end;


Die OnClick-Prozedur für den Abbruch-Button ist elementar einfach:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
procedure TForm1.AbbruchClick(Sender: TObject);
begin
 Form1.Memo1.Lines.Add('Abbruch');
 Abbr:=true;
end;


Innerhalb von Einzelschritt wird übel rumgerechnet. An VCL-Aufrufen finden sich dort nur Form1.Memo1.Lines.Add um Meldungen über den Rechenstand rauszuhauen.

Anzeigen(Feld) enthält ein Befüllen eines StringsGrids Form1.StringGrid1.Cells[i,j]:=...

Mehr ist nicht.

Grüße Elrond

Moderiert von user profile iconGausi: Delphi-Tags hinzugefügt
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Do 16.10.08 16:06 
mach mal break statt exit.
Un Ausserdem sin Globale Variablen böse!

Und wenns denn sein muss, solltest du die wohl auch hier posten!!!!
(Also am besten die ganze unit).
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 16.10.08 16:16 
Hi,

Break statt Exit habe ich bereits ausprobiert und das mit der globalen Variablen (ich weiß, ich weiß) funktioniert prima, solange die Kontrolle an die OnClick-Prozedur geht.

Weißt Du was Dunkel mit "VCL-Aufrufe synchronisieren" meinte?

Grüße

Elrond
Jann1k
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 866
Erhaltene Danke: 43

Win 7
TurboDelphi, Visual Studio 2010
BeitragVerfasst: Do 16.10.08 16:19 
Die Schleife würde ich so machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
 while (b_s_1(Feld) > 0and (not abbr) do
  begin
   einzelschritt;
   anzeigen(Feld);
   Application.ProcessMessages;
  end;



Außerdem sagst du das einzelscritt rechenintensiv ist, wenn einzelschrit der verzögernde Faktor ist, hilft dir das Konstrukt an dieser Stelle gar nichts.


Zuletzt bearbeitet von Jann1k am Do 16.10.08 16:20, insgesamt 2-mal bearbeitet
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Do 16.10.08 16:19 
Du solltest jetzt auch mal den Kompletten Quelltext posten!!!!!!!!!!!!
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8548
Erhaltene Danke: 477

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Do 16.10.08 16:20 
VCL synchronisieren ist hier nicht nötig. Da du nur mit einem Thread (halt dem VCL-Hauptthread) arbeitest, ist das automatisch synchron, da die VCL nur zu sich selbst synchron arbeiten muss. Synchronschwimmen ohne Partner ist auch relativ einfach. ;-)

Wenn mam mit mehreren Threads arbeitet, muss man einige Sachen beachten, damit es nicht an allen Ecken knallt. hier ist das aber nicht nötig.

Wie wird denn die Prozedur loeseAufgabe aufgerufen? Normalerweise sollte das Konstrukt nämlich so funktionieren.

_________________
We are, we were and will not be.
Lossy eX
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 1048
Erhaltene Danke: 4



BeitragVerfasst: Do 16.10.08 16:36 
Den Hinweis von Jann1k find ich auch nicht gerade unwichtig. Wenn diese Schleife nur 3 mal durchlaufen wird und die Methode einzelschritt aber 50 Sekunden rechnet, dann kann es so natürlich nicht funktionieren.

Wenn die Berechnung ohne Zugriffe auf das Formular/Komponenten auskommt (außer gelegentlichen Statusmeldungen), dann sind Threads absolut nicht schwer. Und das ist ja dann das Einzige was wirklich einen Sinn macht. Zu mal übermäßiges Aufrufen von ProcessMessages nur völlkommen unnötig ausbremmst und ProcessMessages durchaus den ein oder anderen Seiteneffekt auslösen kann.

_________________
Nur die Menschheit ist arrogant genug, um zu glauben sie sei die einzige intelligente Lebensform im All. Wo nicht mal das nachhaltig bewiesen wurde.
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 16.10.08 16:38 
Ich hab's...ich hab's... :D :D :D

Innerhalb von anzeigen stand noch eine Leiche aus einem anderen Programm (copy+paste :roll:) und zwar ein Aufruf von

Form1.StringGrid1.SetFocus;

Ohne diesen Aufruf kann ich jetzt mit dem Abbruch-Button problemlos stoppen. Aber auch nur, wenn APM aufgerufen wird. Ohne APM klappt der Abbruch nicht.

Nur mal aus Interesse von einem Neuling: Warum verhindert SetFocus den Abbruch und warum brauche ich immer noch das (angeblich) so böse APM?

Grüße

Elrond
Boldar
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 1555
Erhaltene Danke: 70

Win7 Enterprise 64bit, Win XP SP2
Turbo Delphi
BeitragVerfasst: Do 16.10.08 16:42 
Naja, mit dem Setfocus kannst du nie den Button klicken, da der Focus sofort wieder auf das Stringgrid gesetzt wird!

Hättest du den Code hier gepostet, hätte dir das hier gleich jemand sagen können. Die Lösung mit Threads ist wohl trotzdem besser!
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 16.10.08 16:44 
user profile iconJann1k hat folgendes geschrieben Zum zitierten Posting springen:
Die Schleife würde ich so machen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
 while (b_s_1(Feld) > 0and (not abbr) do
  begin
   einzelschritt;
   anzeigen(Feld);
   Application.ProcessMessages;
  end;



Außerdem sagst du das einzelscritt rechenintensiv ist, wenn einzelschrit der verzögernde Faktor ist, hilft dir das Konstrukt an dieser Stelle gar nichts.


Mit der Schleife hast du natürlich recht. Ist eleganter als mit Break. Einzelschritt ist nicht das Problem sondern die Anzahl der Schleifendurchläufe in Kombination mit Einzelschritt. Insofern funktioniert das Ganze jetzt sehr gut.

Grüße

Elrond
Elrond Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Do 16.10.08 16:47 
user profile iconBoldar hat folgendes geschrieben Zum zitierten Posting springen:
Naja, mit dem Setfocus kannst du nie den Button klicken, da der Focus sofort wieder auf das Stringgrid gesetzt wird!


Ergibt Sinn. Ich habe die Befehlsleiche einfach übesehen.

Grüße

Elrond