AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi Exception ohne wirklichen Auslöser treibt mich in den Wahnsinn!
Thema durchsuchen
Ansicht
Themen-Optionen

Exception ohne wirklichen Auslöser treibt mich in den Wahnsinn!

Ein Thema von berens · begonnen am 19. Aug 2013 · letzter Beitrag vom 20. Aug 2013
 
berens

Registriert seit: 3. Sep 2004
441 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Exception ohne wirklichen Auslöser treibt mich in den Wahnsinn!

  Alt 19. Aug 2013, 21:10
Was machst Du denn im Execute des Threads ausserhalb der Synchronize-Aufrufe?
Dadurch, dass ich leider auf eine Access-Datenbank über Netzlaufwerk über <2MBit VPN angewiesen bin, lade ich alle Datensätze über einen Thread direkt in Objekte. Die Objekte werden dann von den Main-Thread kopiert (neu erzeugen und .Assign)


Beispiel:
Laden der Daten aus Datenbank
Delphi-Quellcode:
  TProjekt = class(TLoadSaveItem)
  public
    txtProjektName: string;
    dtEndDatum: TDateTime;
    dtStartDatum: TDateTime;
    blAusblenden: Boolean;
    function Equals(_CompareTo: TProjekt): Boolean;
    procedure Assign(_Source: TPersistent); override;
    constructor Create(_Owner: TComponent); override;
  end;


            while (not q.Eof) and (not FblStop) and (ToDo = 0) do begin
              inc(intCounter);
// OutputDebugString(pchar('LoadSave.Laden.Projekte.Counter: ' + inttostr(intCounter)));

              tmpProjekt := TProjekt.Create(NIL);
              with tmpProjekt do begin
                ID := q.FieldByName('ID').AsInteger;
                dtEndDatum := floor(q.FieldByName('dtEndDatum').AsDateTime);
                dtStartDatum := floor(q.FieldByName('dtStartDatum').AsDateTime);
                txtProjektName := q.FieldByName('txtProjektName').AsString;
                blAusblenden := q.FieldByName('blAusblenden').AsBoolean;
                LastUpdate := CurrentTick;
              end;

              // Genau dieses Projekt in der Liste der bereits geladenen Projekte suchen
              blGefunden := False;
              for i := 0 to FclProjekte.Count - 1 do begin
                if FclProjekte.Items[i].InheritsFrom(TProjekt) then begin
                  ListenProjekt := TProjekt(FclProjekte.Items[i]);
                  // Projekt gefunden
                  if ListenProjekt.ID = tmpProjekt.ID then begin
                    ListenProjekt.Assign(tmpProjekt);
                    blGefunden := True;
                    Break;
                  end;
                end;
              end;

              if blGefunden then begin
                FreeAndNil(tmpProjekt);
              end else begin
                Synchronize(SyncNewDataset);
                FclProjekte.Add(tmpProjekt);
              end;

              q.Next;
              Synchronize(SyncSaveAndDelete); // damit auch beim Laden abgebrochen werden kann

              if (intCounter mod 10 = 0) then begin
                FProgressText := Format('%s von %s Projekten geladen', [IntToStr(intCounter), IntToStr(q.RecordCount)]);
                Synchronize(SyncProgress);
              end;
            end;

            q.Close;
            q.SQL.Clear;

            try
              i := 0;
              // Alle Einträge durchgehen
              while i < FclProjekte.Count do begin

                // Wenn Eintrag in der Liste nicht beim aktuellen Neu-Lade Zyklus mit dabei war
                tmpLS := TLoadSaveItem(FclProjekte.Items[i]);
                if tmpLS.LastUpdate <> CurrentTick then begin
                  FclProjekte.Delete(i);
                end else begin
                  inc(i);
                end;
              end;
            except end;

            Synchronize(SyncProjekte);
            FProgressText := Format('%s Projekte geladen', [IntToStr(intCounter)]);
            Synchronize(SyncProgress);
          end;
Und dann mit Synchronize die in Objekte aus der THREAD-Componentliste (FclProjekte) in die VCL (Main-Thread)-Componentenliste (clProjekte) kopieren mittels assign.

Sollte ja nix ausmachen, dass die clProjekte ein Objekt des Threads ist? Schließlich wird ja mit .Execute NIE direkt darauf zugegriffen...
Delphi-Quellcode:
{$Region 'procedure TLoadSaveThread.SyncProjekte;'}
procedure TLoadSaveThread.SyncProjekte;
var
  i, j: integer;
  blGeloescht, blGefunden: Boolean;
  tmpProjekt: TProjekt;
begin
  SyncStop;
  try
    if FblStop then Exit;
    if FclProjekte.Count = 0 then Exit;

    while clProjekte.Count > 0 do begin
      tmpProjekt := TProjekt(clProjekte.Extract(clProjekte.Items[0]));
      FreeAndNil(tmpProjekt);
    end;
    if FblStop then Exit;
  except end;

  {$Region 'Alle Projekte aus dem Thread durchgehen'}
  try
    for i := 0 to FclProjekte.Count - 1 do begin
      if TLoadSaveItem(FclProjekte.Items[i]).InheritsFrom(TProjekt) then begin
        tmpProjekt := TProjekt.Create(NIL);
        tmpProjekt.Assign(TProjekt(FclProjekte.Items[i]));

        // Wurde das aktuelle Projekt zwischenzeitlich gelöscht?
        blGeloescht := False;
        for j := 0 to FclDelete_Outbox.Count - 1 do begin
          if TLoadSaveItem(FclDelete_Outbox.Items[j]).InheritsFrom(TProjekt) then begin
            if TLoadSaveItem(FclDelete_Outbox.Items[j]).ID = tmpProjekt.ID then begin
              blGeloescht := True;
              Break;
            end;
          end;
        end;

        // Falls gelöscht, nicht in die VCL-Liste übernehmen
        if blGeloescht then begin
          FreeAndNil(tmpProjekt);
        end else begin
          // Falls nicht gelöscht, nachsehen
          // ob dieser Eintrag zwischenzeitlich bearbeitet und gespeichert wurde.
          // Dann diesen Wert bevorzugen, denn das Abspeichern in der Datenbank ist noch nicht beendet.

          j := 0;
          while j < FclSave_Outbox.Count do begin
            if TLoadSaveItem(FclSave_Outbox.Items[j]).InheritsFrom(TProjekt) then begin
              if TLoadSaveItem(FclSave_Outbox.Items[j]).ID = tmpProjekt.ID then begin
                // falls das Objekt aus dem Datenbankthread identisch ist mit dem, was gespeichert werden soll,
                // war das speichern und anschließende Neu-Laden wohl erfolgreich.
                if TProjekt(FclSave_Outbox.Items[j]).Equals(tmpProjekt) then begin
                  FclSave_Outbox.Delete(j);
                end else begin
                  // Abspeichern noch nicht beendet, deswegen Daten aus der Datenbank mit denen aus dem Zwischenspeicher ersetzen
                  tmpProjekt.Assign(FclSave_Outbox.Items[j]);
                  inc(j);
                end;
              end else inc(j);
            end else inc(j);
          end;

          clProjekte.Add(tmpProjekt);

        end;

      end; // inheritsfrom TProjekt
    end; // Alle Projekte
  except end;
  {$EndRegion 'Alle Projekte aus dem Thread durchgehen'}

  {$Region '"Zu speichernde" -also neue- Projekte laden'}
  try
    i := 0;
    while i < FclSave_Outbox.Count do begin

      // Ist das "zu speichernde" Projekt (in Save_Outbox) denn "schon" in clProjekte enthalten?
      blGefunden := False;
      for j := 0 to clProjekte.Count - 1 do begin
        if TLoadSaveItem(clProjekte.Items[j]).ClassType = TLoadSaveItem(FclSave_Outbox.Items[i]).ClassType then begin
          if TLoadSaveItem(clProjekte.Items[j]).ID = TLoadSaveItem(FclSave_Outbox.Items[i]).ID then begin
            blGefunden := True;
          end;
        end;
      end;

      // Falls noch nicht in clProjekte vorhanden
      if not blGefunden then begin
        if FclSave_Outbox.Items[i].InheritsFrom(TProjekt) then begin
          tmpProjekt := TProjekt.Create(NIL);
          tmpProjekt.Assign(TProjekt(FclSave_Outbox.Items[i]));
          clProjekte.Add(tmpProjekt);
        end;
      end;

      inc(i);
    end;
  except end;
  {$EndRegion '"Zu speichernde" -also neue- Projekte laden'}

  {$Region 'Wurde das zu löschende Projekt nicht mehr erneut aus der Datenbank geladen?'}
  try
    i := 0;
    // Liste der zu löschenden Objekte durchgehen
    while i < FclDelete_Outbox.Count do begin

      blGefunden := False;
      // vergleichen mit dem, was eben geladen wurde
      for j := 0 to FclProjekte.Count - 1 do begin
        if TLoadSaveItem(FclProjekte.Items[j]).ClassType = TLoadSaveItem(FclDelete_Outbox.Items[i]).ClassType then begin
          // Falls das zu löschende Objekt immer noch in der Liste gefunden wird, abbrechen
          if TLoadSaveItem(FclProjekte.Items[j]).ID = TLoadSaveItem(FclDelete_Outbox.Items[i]).ID then begin
            blGefunden := True;
            Break;
          end;
        end;
      end;

      // Wenn das zu löschende Objekt nicht mehr aus der Datenbank geladen wird, wurde es erfolgreich gelöscht
      if blGefunden then begin
        inc(i);
      end else begin
        // Nachverfolgung erfolgreich, da der zu löschende Datensatz nicht erneut aus der Datenbank geladen wurde!
        FclDelete_Outbox.Delete(i);
      end;
    end;
  except end;
  {$EndRegion 'Wurde das zu löschende Projekt nicht mehr erneut aus der Datenbank geladen?'}

end;
{$EndRegion}
  Mit Zitat antworten Zitat
 

 

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 14:38 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz