AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Zugriff von Threads auf Instanzen, wo CriticalSection def.?
Thema durchsuchen
Ansicht
Themen-Optionen

Zugriff von Threads auf Instanzen, wo CriticalSection def.?

Ein Thema von s.h.a.r.k · begonnen am 19. Sep 2008 · letzter Beitrag vom 22. Sep 2008
 
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#1

Zugriff von Threads auf Instanzen, wo CriticalSection def.?

  Alt 19. Sep 2008, 11:39
hallo,

ich beziehe mich hierbei auf diesen Thread, wobei diese fragestellung, in meinen augen, nichts mehr mit dem problem hier zu tun hat, daher ein neues Topic.

und zwar geht es darum, dass ich eine klasse habe, die datenbankabfragen tätigt. diese hat drei public-methoden, die allerdings, nur mit angepassten parametern, eine private-methode aufrufen. hier vorab schon mal der 1:1 code von der private-methode.
Delphi-Quellcode:
// private-Methode
function TDatabase._execSQL(SQL: String; var ATable: TADDatSTable): Boolean;
var
  cmd : Char;
  b : Boolean;
  sqlList : TStringList;
  s : String;
begin
  Result := False;
  SQL := trim(SQL);

  // Auf Verbindung prüfen
  if not FConnection.Connected then
    exit;

  try
    // Länge des SQL-Befehls prüfen
    if (length(SQL) < 1) then
      raise Exception.Create('Es wurde kein SQL-Befehl übergeben');

    // SQL-Befehl prüfen
    cmd := SQL[1];
    if (not (cmd in ALLOWED_DATABASE_COMMANDS) ) then
      raise Exception.Create('Es wurde kein korrekter SQL-Befehl übergeben');

    // Unerlaubte Zeichen auskommentieren (für Oracle)
    maskSpecialChars(SQL);

    sqlList := TStringList.Create;
    try
      // SQL in Zeilen aufsplitten, in so fern #13 im SQL-String vorkommen
      while pos(#13, SQL) > 0 do
      begin
        s := copy(SQL, 1, pos(#13, SQL) - 1);
        delete(SQL, 1, pos(#13, SQL));
        sqlList.Add(trim(s));
      end;
      sqlList.Add(SQL); // letzter Part bzw alleiniger SQL-Befehl ohne mehrere Zeilen

      // Kritische Sektion betreten
      FCriticalSection.Enter();
      // SQL ausführen
      try
        FCommand.CommandText := sqlList;
        if (cmd = 'S') then
        begin
          try
            if not Assigned(ATable) then
              exit;

            // SELECT-Abfrage mit Ergebnisausgabe
            FCommand.Open; // Abfrage wird an DB gesendet und Ergebnis wird in Empfang genommen
            FCommand.Define(ATable); // Tabelle bekommt hier die Spalten mitgeteilt
            FCommand.Fetch(ATable, True); // Übertrag der empfangenen Daten an die Tabelle
            FCommand.Close;
            Result := True;
          except
            raise;
          end;
        end
        else begin
          // -> Exception, wenn die Abfrage nicht geklappt hat
          // ansonsten tritt kein Fehler auf
          try
            FCommand.Execute();
            Result := True;
          except
            raise;
          end;
        end;
      finally
        // Kritische Sektion wieder freigeben
        FCriticalSection.Release();
      end;
    except
      on E : Exception do
      begin
        // Wenn es zu einer internen Exception kommt, dann wird nur in die
        // Log-Datei geloggt, da es sonst unter Umständen zu einer Endlos-
        // schleife werden kann
        b := FLog.LogToDatabase;
        FLog.LogToDatabase := False;
        Log(E.Message, ltError);
        FLog.LogToDatabase := b;
      end;
    end;
  finally
    FreeAndNil(sqlList);
  end;
end;
die public-methoden, die eben die private-methode aufrufen, haben die folgenden aufgaben: einerseits das handling von select-abfragen, also mit ergebnis-tabelle, zum anderen inserts, delete etc, mit ergebnis über den erfolg und das dritte wäre die transaktion (nur inserts, delete etc.), eben auch mit dem ergebnis über erfolg der queries.
Delphi-Quellcode:
function execSQL(aSQL: String): Boolean;
var
  tmp : TADDatSTable;
begin
  { ... }
  Result := _execSQL(aSQL, tmp);
  { ... }
end;

function execSQL(aSQL: String; var aTable: TADDatSTable): Boolean;
begin
  { ... }
  Result := _execSQL(aSQL, aTable);
  { ... }
end;

function execTransaction(aSQLList: TStringList): Boolean;
var
  i : Integer;
  tmp
begin
  { ... }
  { Transaktion wird gestartet}
  Result := True;
  for i := 0 to aSQLList.Count - 1 do
  begin
    if not (execSQL(aSQLList[i])) then
    begin
      Result := False;
      break;
    end;
  end;
  { Transaktion wird beendet }
  { ... }
end;
zudem ist noch zu sagen, dass ich die variable FCriticalSection : TCriticalSection in der klasse TDatabase private definiert habe.

nun zum eigentlichen problem: in zeile 41 der private-methode betrete ich ja die kritische sektion und jeder andere thread, der eben ein query ausgeführt haben möchte wartet an dieser stelle -- so habe ich das bisher halt verstanden. wenn der thread, der gerade den code ausführt, d.h. andere threads blockiert, zeile 73 erreicht so gibt er diesen abschnitt für andere threads wieder frei und der nächste thread kann diesen code ausführen. blockiert allerdings wieder die anderen threads.

die frage hierbei ist: ist das die richtige position, in so fern ich einen normalen query ausführe, also noch keine transaktion, da dies ein gesondertes problem darsellt??? was passiert mit den variablen innerhalb der methode _execSQL, wenn zwei threads mehr oder weniger gleichzeitig in diese methode rein laufen und diesen code ausführen, eben bis zur besagten stelle? was passiert dabei im speichern? werden zwei "instanzen" (ich weiß nicht, wie man dazu sagt) von dieser methode im speicher gehalten, oder nur eine? denn dann könnte ja das problem auftreten, dass die variablen in der methode überschrieben werden, eben ein zweiter thread die daten überschreibt, die der ausführende thread gerader braucht!?

ich hoffe, ihr könnt mir hierbei etwas weiterhelfen.

vielleicht noch eine frage am rande: wie lange wartet ein thread eigentlich, wenn er nicht sofort den code ausführen kann? halt er einfach an dieser stelle an, oder wird ein neues execute aufgerufen?

hätte jemand evtl. ein sehr ausführliches tutorial über threads? wäre echt klasse. habe das von luckie schon gelesen, aber das geht mir nicht ausreichend ins detail!

mit freundlichen grüßen
der hai
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  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 18:30 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