AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Datenbanken TSQLDataSet, TSQLConnection Multithread Exception
Thema durchsuchen
Ansicht
Themen-Optionen

TSQLDataSet, TSQLConnection Multithread Exception

Ein Thema von Barthiboy · begonnen am 4. Dez 2015 · letzter Beitrag vom 11. Dez 2015
Antwort Antwort
Benutzerbild von baumina
baumina

Registriert seit: 5. Mai 2008
Ort: Oberschwaben
1.275 Beiträge
 
Delphi 11 Alexandria
 
#1

AW: TSQLDataSet, TSQLConnection Multithread Exception

  Alt 4. Dez 2015, 11:10
Du könntest z.B. debuggen und sagen wo welche Fehlermeldung auftaucht, oder du könntest den Quellcode des Threads zeigen, wo z.B. wie synchronisiert wird. Eine Zugriffsverletzung ist meist ein Hinweis auf einen Zugriff auf ein Objekt, das bereits freigegeben wurde, dass die SQL-Statements das auslösen ist recht unwahrscheinlich.
Hinter dir gehts abwärts und vor dir steil bergauf ! (Wolfgang Ambros)
  Mit Zitat antworten Zitat
Barthiboy

Registriert seit: 4. Nov 2011
36 Beiträge
 
#2

AW: TSQLDataSet, TSQLConnection Multithread Exception

  Alt 4. Dez 2015, 11:30
Na das is doch mal eine Ansage.
Mach ich doch gleich so gut ich kann.

ich habe jetzt mit einem try-except endlich eine genauere Fehlerbeschreibung:
04.12.2015 11:19:27 Client : Exception = Zugriffsverletzung bei Adresse 000000000BB4768C in Modul 'dbxmss.dll'. Lesen von Adresse FFFFFFFFFFFFFFFF
04.12.2015 11:20:16 Client : Exception = Zugriffsverletzung bei Adresse 000000000BB47680 in Modul 'dbxmss.dll'. Lesen von Adresse 0000000000000082

Der Thread sieht in etwa so aus

Delphi-Quellcode:
        
if DataCount > 0 then begin
          // Daten einlesen
          SendStr := 'Worksation;' + FormatDateTime('yyyy.mm.dd hh-nn-ss', now) + ';' + IntToStr(SessionID) + ';FetchDataToTransmit##';
          FIdTCPClient.IOHandler.WriteLn(SendStr, nil);

          for j := 0 to Datacount - 1 do begin
            if not KommEnable then begin
              // Wenn der Benutzer die Kommunikation pausiert, hier warten bis es weiter geht!
              FIdTCPClient.Disconnect;
              Logged := false;
              break;
            end;
            for i := 0 to 21 do begin
              Count := FIdTCPClient.IOHandler.ReadLongInt(false);
              RecStr := FIdTCPClient.IOHandler.ReadString(Count, nil);
              Logger.LogMessage('Server : ' + RecStr);
              if DataExport then begin
                SLStr := SLStr + #9 + RecStr;
              end;
              Daten[i] := RecStr;
              if i = 21 then begin
                if not DataNotInDB then begin // doppelte Verneinung (;
                  if Produkt_Auswerten(Daten) < 0 then begin
                    KommEnable := false;
                  end
                end;
              end;
              RemainCount := Datacount - j - 1;
              // Wenn nichts abzuholen ist
              if RemainCount < 0 then RemainCount := 0;
              // Ack senden
              SendStr := '1';
              Logger.LogMessage('Client : ' + SendStr);
              FIdTCPClient.IOHandler.Write(SendStr, nil);
            end;
            // Einen Datensatz komplett gelesen
            if DataExport then begin
              SLDaten.Add(SLStr);
              SLStr := '';
            end;
            if Terminated then begin
              Break;
            end;
          end;
Und Das updaten der Anzeige im Main wird von einem Timer getriggert und sieht dann so aus

Delphi-Quellcode:
  if SQLC_Work.Connected then begin
    try
      SQLDS_Work.Close;
      // Aktuellen Wareneingang ermitteln
      SQLDS_Work.Close;
      SQLDS_Work.CommandText := 'SELECT COUNT(WareneingangsNr) from WEP02.dbo.WareneingangsNr WHERE Aktiv = 1';
      SQLDS_Work.Open;
      if SQLDS_Work.FieldCount > 0 then begin
        if SQLDS_Work.Fields[0].AsInteger > 1 then begin // Fehler weil mehrere Wareneingänge aktiv
          if Assigned(Logger) then begin
            Logger.LogErrorMessage('Es sind ' + IntToStr(SQLDS_Work.RecordCount) + ' Wareneingänge aktiv. Fehler bei Timer_Chart aufgetreten');
          end;
          Exit;
        end
        else if SQLDS_Work.Fields[0].AsInteger = 0 then begin // Fehler weil kein Wareneingang aktiv
          Exit;
        end
        else if SQLDS_Work.Fields[0].AsInteger = 1 then begin
          SQLDS_Work.Close;
          SQLDS_Work.CommandText := 'SELECT [IdentNr], [WareneingangsNr] from WEP02.dbo.WareneingangsNr WHERE Aktiv = 1';
          SQLDS_Work.Open;
          if SQLDS_Work.FieldCount > 1 then begin
            IdentNr := SQLDS_Work.Fields[0].AsString;
            WENr := SQLDS_Work.Fields[1].AsString;
          end;
        end;
      end;
      IdentNrOrig := IdentNr;
      IdentNr := StringReplace(IdentNr, '-', '', [rfReplaceAll]);
      SQLDS_Work.Close;
      SQLDS_Work.CommandText := 'Select COUNT(Gesamtergebnis) from WEP02.dbo.Teil_' + IdentNr + ' WHERE Gesamtergebnis = 1';
      SQLDS_Work.Open;
      if SQLDS_Work.FieldCount > 0 then begin
        Gut := SQLDS_Work.Fields[0].AsInteger;
      end;
      SQLDS_Work.Close;
      SQLDS_Work.CommandText := 'Select COUNT(Gesamtergebnis) from WEP02.dbo.Teil_' + IdentNr + ' WHERE Gesamtergebnis = 0';
      SQLDS_Work.Open;
      if SQLDS_Work.FieldCount > 0 then begin
        Schlecht := SQLDS_Work.Fields[0].AsInteger;
      end;

      La_Wenummer.Caption.Text := WENr;
      La_Teilenummer.Caption.Text := IdentNr;

      SQLDS_Work.Close;
      SQLDS_Work.CommandText := 'Select (Teilename) from WEP02.dbo.Teile WHERE IdentNr = ' + quotedStr(IdentNrOrig);
      SQLDS_Work.Open;
      if SQLDS_Work.FieldCount > 0 then begin
        Teilename := SQLDS_Work.Fields[0].AsString;
        Delete(Teilename, 1, 4);
        if not TryStrToInt(Teilename, SelectedModell) then begin
          SelectedModell := 0;
        end;
      end;
Offensichtlich knallt es in der dbxmss.dll.
Allerdings wundert mich das, da ich gelesen habe das es bei multithreading keine Probleme gibt,
wenn jeder Thread seine eigene Connection hat.
Die Exceptions treten meistens auf wenn auf Fields[] zugegriffen wird

Danke
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#3

AW: TSQLDataSet, TSQLConnection Multithread Exception

  Alt 4. Dez 2015, 12:33
Mehrere Vorschläge:
Fehler abfangen:
Delphi-Quellcode:
  SQLDS_Work.Close;
  SQLDS_Work.CommandText := 'Select (Teilename) from WEP02.dbo.Teile WHERE IdentNr = ' + quotedStr(IdentNrOrig);
  Try
    SQLDS_Work.Open;
    if SQLDS_Work.FieldCount > 0 then begin
      Teilename := SQLDS_Work.Fields[0].AsString;
      Delete(Teilename, 1, 4);
      if not TryStrToInt(Teilename, SelectedModell) then begin
        SelectedModell := 0;
      end;
    end;
  except
    on e : Exception do begin
      if Assigned(Logger) then begin
        Logger.LogErrorMessage(SQLDS_Work.CommandText);
        Logger.LogErrorMessage(e.Message);
      end;
    end;
  end;
Analog bei allen SQLDS_Work.Open einbauen.
Delphi-Quellcode:
        SQLDS_Work.Open;
        if SQLDS_Work.FieldCount > 0 then begin
ist gut und schön, aber was ist, wenn die Ergebnismenge (warum auch immer) leer ist?
Delphi-Quellcode:
  try
    SQLDS_Work.Open;
    if SQLDS_Work.Active then begin
      if not SQLDS_Work.Eof then begin
        if SQLDS_Work.FieldCount > 0 then begin
          ...
        end;
      end else begin
        if Assigned(Logger) then begin
          Logger.LogErrorMessage(SQLDS_Work.CommandText);
          Logger.LogErrorMessage('sinnvoller Text zur Fehlerbeschreibung (leere Ergebnismenge)...');
        end;
      end;
    end else begin
      if Assigned(Logger) then begin
        Logger.LogErrorMessage(SQLDS_Work.CommandText);
        Logger.LogErrorMessage('sinnvoller Text zur Fehlerbeschreibung (geschlossene Datenmenge) ...');
      end;
    end;
  except
    on e : Exception do begin
      if Assigned(Logger) then begin
        Logger.LogErrorMessage(SQLDS_Work.CommandText);
        Logger.LogErrorMessage(e.Message);
      end;
    end;
  end;
Diese Fehlerbeschreibung hilft nicht wirklich
Zitat:
Die Exceptions treten meistens auf wenn auf Fields[] zugegriffen wird
Da ja an mehreren Stellen auf Fields[] zugegriffen wird, passiert der Fehler bei irgendeinem der Fields[] oder bei einem Bestimmten und wenn bei einem Bestimmten, bei welchem?

Und wenn sie nicht bei Fields[] auftreten, wo denn dann bitte sonst noch?

Ist die Ergebnismenge der Abfrage leer, dürfte ein Zugriff auf Fields[] kaum funktionieren, da es ja keinen Datensatz in der Ergebnismenge gibt und damit FieldCount = 0 ist. Was ich momentan aber nicht weiß und beurteilen kann ist, ob ein Zugriff auf FieldsCount bei einer leeren Ergebnismenge möglich ist oder hier bereits ein Fehler auftreten kann.

1. Abfrage öffnen.
2. prüfen, ob Abfrage geöffent werden konnte.
3. wenn nein, Meldung ausgeben und abbrechen.
4. prüfen, ob Ergebnismenge leer ist.
5. wenn ja, Meldung ausgeben und abbrechen.
6. prüfen, ob Anzahl der erwarteten Felder in der Ergebnismenge vorhanden ist.
7. wenn nein, Meldung ausgeben und abbrechen.
8. Werte auslesen und verarbeiten.

Um alles herum per Try Except unerwartete Fehler abfangen und im Fehlerfalle Meldung ausgeben und abbrechen.

Abbrechen heißt hier: Entweder das Programm beenden oder in einem sicheren und konsistenten Zustand weiterarbeiten.
  Mit Zitat antworten Zitat
quaero

Registriert seit: 25. Apr 2013
38 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: TSQLDataSet, TSQLConnection Multithread Exception

  Alt 4. Dez 2015, 12:47
Warum sollte FieldCount nichts zurückliefern? Selbst bei
Code:
SELECT * FROM relation WHERE 1=0
werden alle Felder der Relation zurückgegeben. Und
Code:
SELECT COUNT(irgendwas) FROM relation
gibt immer auch einen Wert zurück. Selbst wenn kein Datensatz die Bedingung erfüllt oder relation leer ist, wird 0 zurückgeliefert.
quaero

Geändert von quaero ( 4. Dez 2015 um 12:50 Uhr)
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#5

AW: TSQLDataSet, TSQLConnection Multithread Exception

  Alt 4. Dez 2015, 12:55
Wenn dem so ist, können wir diese Fehlerursache ja ausschließen.

Klar, bei 'nem Count bekommt man mindestens 0 zurück, wenn es was nicht gibt.

Was ist bei SQLDS_Work.CommandText := 'SELECT [IdentNr], [WareneingangsNr] from WEP02.dbo.WareneingangsNr WHERE Aktiv = 1'; ?
Wenn's das nicht gibt, ist die Ergebnismenge leer, EoF müsste dann erfüllt sein und FieldCount = 2. Fields[0].AsString geht dann und gibt 'ne leere Zeichenfolge zurück.

Gut, können wir den Fehler auch ausschließen.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.659 Beiträge
 
FreePascal / Lazarus
 
#6

AW: TSQLDataSet, TSQLConnection Multithread Exception

  Alt 4. Dez 2015, 13:32
Ich frage mich was die beiden Code-Auszüge miteinander zu tun haben. Im ersten wird irgendetwas mit einer TCP-Verbindung gemacht, im zweiten werden Daten aus einer DB per SQL abgeholt. Wenn es da irgendwelche Seiteneffekte gibt, tippe ich auf Pointer-Arithmetik von Zauberlehrlingen.

Gruß
K-H

P.S.
was ist mit durchsteppen mittels F7/F8 kann da der Fehler eingegrenzt werden?
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#7

AW: TSQLDataSet, TSQLConnection Multithread Exception

  Alt 4. Dez 2015, 13:45
@p80286

naja, im "Thread" gibt es sowas wie DataNotInDB und DataExport.
Es könnte sich hier unter Umständen, eventuell, vielleicht um Funktionen handeln, die auf uminöse Weise auf die Datenbank zugreifen. Hier ließen sich dann Probleme und Konflikte beim Zugriff auf die Datenbank nicht zwingend ausschließen.

Im Eingangspost heißt es ja u. a.
Zitat:
... in einem Thread Daten via TCPIP von einem Server gelesen werden und in eine MSSQL Datenbank eingegraten werden...
Wie dies konkret funktioniert, ist aus dem zur Verfügung gestellten Quelltext aber leider nicht zu entnehmen.

Momentan gibt es noch zuviele , aus denen gelesen werden muss, um sich dem gestellten Problem anzunähern.
  Mit Zitat antworten Zitat
Antwort Antwort


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 00:48 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 by Thomas Breitkreuz