AGB  ·  Datenschutz  ·  Impressum  







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

Probleme mit u.a. Timern in Array

Offene Frage von "ManuMF"
Ein Thema von ManuMF · begonnen am 21. Apr 2009 · letzter Beitrag vom 29. Apr 2009
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von ManuMF
ManuMF

Registriert seit: 11. Jul 2005
1.016 Beiträge
 
Delphi 6 Personal
 
#1

Probleme mit u.a. Timern in Array

  Alt 21. Apr 2009, 19:43
Hallo,

ich habe ein Programm, das Records mit verschiedene Daten und einen Timer in einem dynamischen Array ablegt. Zu jedem Record wird auch ein Menü-Item angelegt. Wenn nun mehr als 2 Records vorhanden sind, gibt es beim Beenden des Programms verschiedene Fehler (Exception, Runtime Error) bzw. seit neuestem (kann auch daran liegen, dass ich das Programm nicht mehr so lange laufen lasse) ungültige Zeigeroperation.

Die Fehlermeldungen kommen nicht in meinem eigenen Code, sondern nach dem, was in onFormDestroy ausgeführt wird.

Jetzt habe ich drei Fragen:
  • Bisher rufe ich für jeden Timer FreeAndNil auf, wenn ich den jeweiligen Record löschen will, und verschiebe die restlichen Einträge im Array eins nach oben (per Zuweisung). Dann wird das Array mit SetLength gekürzt. Ist das überhaupt die geeignete Methode?
  • Beim Beenden des Programms lasse ich genau diese Routine alle Records löschen. Muss ich das überhaupt oder würde ein SetLength(Array, 0) reichen?
  • Unabhängig von den anderen beiden Fragen, wodurch könnten die Fehlermeldungen entstehen?

Ich kann gerne etwas Code einstellen, müsste aber wissen, von welcher Stelle.
Gruß,
ManuMF

Endlich hab ich was Positives an Vista entdeckt: Das mitgelieferte Mahjongg
  Mit Zitat antworten Zitat
Regan

Registriert seit: 27. Apr 2007
48 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: Probleme mit u.a. Timern in Array

  Alt 21. Apr 2009, 21:10
Hallo,

also mich würde mal die Freigebe-procedure interessieren. Zudem: Es ist nicht nötig, die Länge des Arrays zu verkürzen. Die wird am Ende eh auf 0 gesetzt und behindert dich hier nur. Ein SetLength:=0 sollte man meiner Meinung nach nicht machen, da wird ja nichts freigegeben.

MfG
Regan
  Mit Zitat antworten Zitat
Benutzerbild von ManuMF
ManuMF

Registriert seit: 11. Jul 2005
1.016 Beiträge
 
Delphi 6 Personal
 
#3

Re: Probleme mit u.a. Timern in Array

  Alt 21. Apr 2009, 21:30
Hmm, meinst du beim Löschen? Dann habe ich ja eine "Datenleiche", wenn ich einen weiteren Record hinzufüge.

Die Lösch-Procedure. Es geht übrigens um E-Mail-Konten, MKonten ist das Array of Record.

Delphi-Quellcode:
function KontoLoeschen(lID: Cardinal): Boolean;
  var
    I: Cardinal;
begin
  result := false;

  { außerhalb }

  If not (lID in [Low(MKonten)..High(MKonten)]) then
    exit;

  { 0 Einträge }

  result := (Length(MKonten) > 0);
  if not result then
    exit;

  { 1 Eintrag }

  If (Length(MKonten) = 1) then
  begin
    result := (lID = 0);
    if (Result) then
    begin
      FreeAndNil(MKonten[lID].ITimer);
      SetLength(MKonten, 0);
      exit;
    end;
  end;

  { 2+ Einträge }

  FreeAndNil(MKonten[lID].ITimer);

  { -> verschieben und Rest eins hochrücken }

  case (High(MKonten) - lID) of
    0:
      SetLength(MKonten, High(MKonten));
    1:
    begin
      MKonten[Pred(High(MKonten))] := MKonten[High(MKonten)];
      SetLength(Mkonten, Pred(High(Mkonten)));
    end;
    else
    begin
      for I := lID to (Length(MKonten) - 2) do
      MKonten[I] := MKonten[Succ(I)];

      SetLength(MKonten, Pred(Length(MKonten)));
    end;
  end;

  result := true;

  { MenuItem suchen und löschen }

  for I := Pred(MCForm.M_Check.Count) downto 0 do
    if (MCForm.M_Check.Items[I].Tag = Succ(lID)) then
      MCForm.M_Check.Delete(I);
end;
Gruß,
ManuMF

Endlich hab ich was Positives an Vista entdeckt: Das mitgelieferte Mahjongg
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#4

Re: Probleme mit u.a. Timern in Array

  Alt 22. Apr 2009, 09:09
Delphi-Quellcode:
function KontoLoeschen(lID: Cardinal): Boolean;
  var
    I: Cardinal;
begin
  result := false;

  { außerhalb } 

  If not (lID in [Low(MKonten)..High(MKonten)]) then
    exit;

(* wird bereits durch die vorherige Bedingung abgedeckt
  { 0 Einträge }

  result := (Length(MKonten) > 0);
  if not result then
    exit;
*)

(* überflüssige Sonderbehandlung
  { 1 Eintrag }

  If (Length(MKonten) = 1) then
  begin
    result := (lID = 0);
    if (Result) then
    begin
      FreeAndNil(MKonten[lID].ITimer);
      SetLength(MKonten, 0);
      exit;
    end;
  end;
*)

  { 2+ Einträge } 
(* Free reicht eigentlich, der Eintrag wird sowieso gleich überschrieben *)
  FreeAndNil(MKonten[lID].ITimer);

  { -> verschieben und Rest eins hochrücken } 
(* überflüssige Sonderbehandlung
  case (High(MKonten) - lID) of
    0:
      SetLength(MKonten, High(MKonten));
    1:
    begin
      MKonten[Pred(High(MKonten))] := MKonten[High(MKonten)];
      SetLength(Mkonten, Pred(High(Mkonten))); <- FEHLER ein Element zu viel gelöscht
    end;
    else
    begin
      for I := lID to (Length(MKonten) - 2) do
      MKonten[I] := MKonten[Succ(I)];

      SetLength(MKonten, Pred(Length(MKonten)));
    end;
  end;
*)


  for I := lID to (Length(MKonten) - 2) do
    MKonten[I] := MKonten[Succ(I)];

  SetLength(MKonten, Pred(Length(MKonten)));
 
  result := true;

  { MenuItem suchen und löschen } 

  for I := Pred(MCForm.M_Check.Count) downto 0 do
    if (MCForm.M_Check.Items[I].Tag = Succ(lID)) then
      MCForm.M_Check.Delete(I);
end;
Edit:
Was passiert eigentlich mit dem Tag der nachfolgenden Menüelemente, müsste der nicht auch angepasst werden?
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.580 Beiträge
 
Delphi 11 Alexandria
 
#5

Re: Probleme mit u.a. Timern in Array

  Alt 22. Apr 2009, 09:19
Du könntest statt Records Klassen verwenden, die den Timer selbst beim Zerstören der Instanz sauber freigeben. Dann könntest du auch eine TObjectList verwenden mit OwnsObjects auf True und müsstest dich um die Freigabe nicht mehr kümmern. Dann müsstest du nur noch einmal Delete aufrufen um einen Eintrag zu zerstören. Das würde sehr viel Arbeit abnehmen.

Ein Timer innerhalb eines Records in einem dynamischen Array hört sich allerdings nach einem recht seltsamen Konstrukt an, vielleicht wäre da ein besseres Konzept sinnvoll.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von ManuMF
ManuMF

Registriert seit: 11. Jul 2005
1.016 Beiträge
 
Delphi 6 Personal
 
#6

Re: Probleme mit u.a. Timern in Array

  Alt 23. Apr 2009, 12:19
Danke für den Tipp, damit werde ich mich mal beschäftigen, das hört sich sehr gut an.
Auf die "seltsame Konstruktion" bin ich gekommen, weil im onTimer jeweils der Aufruf der Prüfprozedur (Anzahl E-Mails) erfolgt. Ich wollte ursprünglich nur einen einzelnen Timer für alle Konten verwenden, allerdings hätte das Probleme gegeben, wenn z.B. die Prüfprozedur aufgerufen wird und im nächsten Durchlauf schon wieder ein anderes Konto aufrufen müsste, bevor die letzte Prüfung fertig war. Kann aber auch ein Denkfehler sein, denn ausprobiert habe ich es noch nicht.

@Blup: Den Tag nehme ich nur als fortlaufenden Index, der nicht der Position des Kontos im Array entspricht (sonst müsste ich den bei jedem Löschen auch verändern). Der Tag ist mit dem des Timers identisch, dadurch kann ich allen Timern das gleiche Event zuweisen und darin das Konto ermitteln:
Delphi-Quellcode:
procedure TMCForm.PostPruefenAufruf(Sender: TObject);
begin
  PostPruefen(Pred(TTimer(Sender).Tag));
end;
Dann werde ich mich jetzt mal an die Überarbeitung der Lösch-Procedure bzw. die ObjectList machen
Gruß,
ManuMF

Endlich hab ich was Positives an Vista entdeckt: Das mitgelieferte Mahjongg
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.580 Beiträge
 
Delphi 11 Alexandria
 
#7

Re: Probleme mit u.a. Timern in Array

  Alt 23. Apr 2009, 16:55
Zitat von ManuMF:
Ich wollte ursprünglich nur einen einzelnen Timer für alle Konten verwenden, allerdings hätte das Probleme gegeben, wenn z.B. die Prüfprozedur aufgerufen wird und im nächsten Durchlauf schon wieder ein anderes Konto aufrufen müsste, bevor die letzte Prüfung fertig war.
Eine bessere Variante wäre die Arbeit mit Threads. Da könnte jedes Konto einen eigenen haben und ggf. neue Daten per Synchronisation ans Programm weitergeben.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Blup

Registriert seit: 7. Aug 2008
Ort: Brandenburg
1.464 Beiträge
 
Delphi 12 Athens
 
#8

Re: Probleme mit u.a. Timern in Array

  Alt 24. Apr 2009, 13:36
Zitat von ManuMF:
@Blup: Den Tag nehme ich nur als fortlaufenden Index, der nicht der Position des Kontos im Array entspricht (sonst müsste ich den bei jedem Löschen auch verändern). Der Tag ist mit dem des Timers identisch, dadurch kann ich allen Timern das gleiche Event zuweisen und darin das Konto ermitteln:
Delphi-Quellcode:
procedure TMCForm.PostPruefenAufruf(Sender: TObject);
begin
  PostPruefen(Pred(TTimer(Sender).Tag));
end;
Dann werde ich mich jetzt mal an die Überarbeitung der Lösch-Procedure bzw. die ObjectList machen
Die an die Löschprozedur übergebene lID wird aber als Position des Kontos im Array behandelt.
Zumindest um den Timer zusammen mit dem Eintrag im Array zu löschen.
Wenn diese nicht mit dem Tag des Timer und des MenuItem übereinstimmt, dann muss dieser Tag aus dem Timer ermittelt werden, um das richtige Menüitem zu löschen.
Delphi-Quellcode:
function KontoMenuLoeschen(lTag: Cardinal): Boolean;
var
  i: Integer;
begin
  { MenuItem suchen und löschen } 
  for i := Pred(MCForm.M_Check.Count) downto 0 do
  begin
    Result := (MCForm.M_Check.Items[i].Tag = lTag);
    if Result then
    begin
      MCForm.M_Check.Delete(i);
      Exit;
    end;
  end;
  Result := False;
end;

{...}
KontoMenuLoeschen(MKonten[lID].ITimer.Tag);
FreeAndNil(MKonten[lID].ITimer);
{...}
  Mit Zitat antworten Zitat
Benutzerbild von ManuMF
ManuMF

Registriert seit: 11. Jul 2005
1.016 Beiträge
 
Delphi 6 Personal
 
#9

Re: Probleme mit u.a. Timern in Array

  Alt 24. Apr 2009, 18:32
Stimmt, du hast Recht - da war noch ein großer Denkfehler
Gruß,
ManuMF

Endlich hab ich was Positives an Vista entdeckt: Das mitgelieferte Mahjongg
  Mit Zitat antworten Zitat
Benutzerbild von ManuMF
ManuMF

Registriert seit: 11. Jul 2005
1.016 Beiträge
 
Delphi 6 Personal
 
#10

Re: Probleme mit u.a. Timern in Array

  Alt 28. Apr 2009, 21:13
Die Konten werden nun in einer ObjectList gespeichert und das Problem mit dem Index ist auch behoben - danke für die Tipps

Beim Beenden kommt immer noch eine Ungültige Zeigeroperation. Und zwar in einem onTimer. Den Timer lasse ich jede Sekunde die Restzeit bis zur nächsten Prüfung für jedes Konto berechnen - soviel zur Erklärung.
Ich habe jetzt probiert, eine Variable beim Beenden (Klicken im Menü oder Message von Windows) auf true zu setzen. Am Anfang der Timer-Prozedur und in der Schleife prüfe ich die Variable und verlasse das ggf. per break/exit. Trotzdem kommt die Meldung. Wenn ich alles in der Timer-Prozedur auskommentiere, funktioniert es. Woran kann denn das jetzt noch liegen?
Gruß,
ManuMF

Endlich hab ich was Positives an Vista entdeckt: Das mitgelieferte Mahjongg
  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 09:51 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