Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Eigener Dienst beendet nicht korrekt... (https://www.delphipraxis.net/127539-eigener-dienst-beendet-nicht-korrekt.html)

cherry 15. Jan 2009 07:54


Eigener Dienst beendet nicht korrekt...
 
Hi

Mein Dienst beendet manchmal korrekt, manchmal nicht. Nicht nur beim manuellen start/stop sondern auch beim Herunterfahren des PC's...

Wenn ich den Dienst manuell beende erhalte ich manchmal die Meldung: "Dienst konnte nicht beendet werden" und die Function "Update Userinfo" wird nicht mehr ausgeführt.

Beim Herunterfahren des PCs werden ja alle Dienste beendet, doch meiner scheint dies nicht korrekt zu tun, denn auch hier wird die Function "Update Userinfo" nicht immer ausgeführt.

Delphi-Quellcode:
procedure TMeinDienst.ServiceShutdown(Sender: TService);
begin
  UpdateUserInfo(Username, false);
  LogFile.LOG(msg0009);
end;
Hier das Execute...

Delphi-Quellcode:
procedure TMeinDienst.ServiceExecute(Sender: TService);
begin
  //ShowMessage('OnExecute - begin');
  while not Terminated do
  begin
    TRY
      // try to catch a user
      if Username <> '' then
      begin
        // AUTOSCAN
        // THIS SECTION IS FOR USER WHO JUST LOGGED IN
        if (Username <> GetSession) or (Welcome = False) then
        begin
          ChangeUser;
          if Username <> '' then // its important to get sure that the username has really been catched
          begin
            Welcome := True;
            LogFile.Log(msg0004+GetIPAddress);
            // check if the user already exists in the database
            CheckDBforUser(ADOQuery1,ADOStoredProc1);
            // Save to database that the user is logged in
            UpdateUserInfo(Username, true);
            // get all info from User Table "t_bb_user"
            ADOQuery3.Close;
            ADOQuery3.Parameters.ParamValues['@username'] := username;
            ADOQuery3.Open;

            // If the logged in user is not on the blacklist it will autoscan now
            if CheckUserOnBlacklist(Username) = False then
            begin
              // autostart scan now, but first get defined scan_type from db!
              case ADOQuery3scan_type.AsInteger of
                0: begin ScanAndWriteToDB(True, stNoScanNoWrite); end;
                1: begin ScanAndWriteToDB(True, stFullScanWriteJustRootFoldersSize); end;
                2: begin ScanAndWriteToDB(True, stFullScanAndWrite); end;
              end;
            end
            else
            begin
              // user is on blacklist, but login info will be saved
              ScanAndWriteToDB(True, stNoScanNoWrite);
              LogFile.Log(Username+msg0016);
            end;

            // activate TCP server
            if not assigned(TCPServer) then
              ActivateTCPServer;

          end;
        end
        else if StartManScan then
        begin
          try
            // check if the user already exists in the database, else it will create him
            if Username <> '' then
            begin
              CheckDBforUser(ADOQuery1,ADOStoredProc1);
              ScanAndWriteToDB(False, stFullScanAndWrite);
            end;
          finally
            // its very important to reset the variable StartManScan
            StartManScan := False;
            // send to the requesting host that the scan is complete now...
            Connect;
            TCPClient.IOHandler.WriteLn(IntToStr(CmdScanFinished));
            // disconnect
            Disconnect;
          end;
        end;
      end
      else
      begin
        ChangeUser;
        Welcome := False;
      end;
    EXCEPT
      on e:Exception do
      begin
        LogFile.LOG(msg0000+e.Message);
        // maby there are some tcp actions pending...
        Disconnect;
        if fulllog then LogFile.Log(msg0039);
      end;
    END;
      ServiceThread.ProcessRequests(False);
      Sleep(1000);
  end;
  //ShowMessage('OnExecute - end');
end;
Bitte wirf doch mal ein Blick drauf.. PS: und wenn du gleich andere Sachen siehst die man anders strukturieren müsste, dann lass es mich wissen...

LG
Cherry

franktron 15. Jan 2009 08:13

Re: Eigener Dienst beendet nicht korrekt...
 
Greift

Delphi-Quellcode:
  UpdateUserInfo(Username, false);
auf eine DB zu, wenn ja dann musst du die Abhängigkeiten für diesen Dienst änder.

nahpets 15. Jan 2009 08:17

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,

Du greifst auf eine Datenbank zu, läuft die zufällig auf dem gleichen Rechner? Dann könnte es sein, dass die (zumindest beim Herunterfahren) vor Deinem Dienst beendet wurde.
Soweit ich weiß ist die Reihenfolge, in der Dienste beim Runterfahren beendet werden, nicht definiert, daher mal das: geht / geht nicht. Das ist natürlich keine Erklärung für das manuelle Stoppen des Dienstes.

Da Du eine Methode zum Loggen hast, schreib da mal etwas mehr mit in die Logdatei, z. B. vor jeden Funktions- bzw. Prozeduraufruf ala
Delphi-Quellcode:
LogFile.Log(msg4711+'vor ADOQuery.Open');
Damit der Änderungsaufwand für diese Form des "von Hand debuggen" nicht zu groß wird, mache ich das meistens so:
Am Anfang der Unit steht ein
Delphi-Quellcode:
{$DEFINE VERBOSE}
das bei (hoffentlicher) Fehlerfreiheit auskommentiert wird. Das Loggen steht dann in der Form im Quelltext:
Delphi-Quellcode:
{$IFDEF VERBOSE}
LogFile.Log(msg4711+'vor ADOQuery.Open')
;{$ENDIF}
Eventuell solltest Du dem Try-Finally-Block noch einen zusätzlichen Try-Except-Block gönnen, um dort auftretende Fehler loggen zu können.
Ausgehend von Deinem geposteten Quelltext kann ich auf die Schnelle kein grundlegendes Problem erkennen. Da Du aber etliche Methoden aufrufst, könnte dort irgendwo ein "Hänger" sein, z. B. ein Timeout, dass höher ist, als die Wartezeit, die Deinem Dienst beim Beenden vom Betriebssystem gegönnt wird. Und wenn mehrere Methoden auf ein Timeout warten oder nur mit nicht allzu kurzen Wartezeiten zu tuen haben, könnte das zu diesem sporadischen Problem führen.

cherry 15. Jan 2009 08:30

Re: Eigener Dienst beendet nicht korrekt...
 
Danke für die schnelle Antworten. Erstmal:

Zitat:

Zitat von nahpets
Hallo,
Du greifst auf eine Datenbank zu, läuft die zufällig auf dem gleichen Rechner?

Ne, die MSSQL Datenbank läuft auf einem Server.

Zitat:

Zitat von franktron
Greift
Delphi-Quellcode: markieren
UpdateUserInfo(Username, false);
auf eine DB zu, wenn ja dann musst du die Abhängigkeiten für diesen Dienst änder.

Ja tut es. Was für Abhängigkeiten meinst du? -Wie soll ich das realisieren...

Zitat:

Zitat von nahpets
Da Du eine Methode zum Loggen hast, schreib da mal etwas mehr mit in die Logdatei, z. B. vor jeden Funktions- bzw. Prozeduraufruf ala...

Ok, da auch Ihr auf den ersten Blick keinen Fehler sieht, werde ich das Problem so mal probieren einzugrenzen.

nahpets 15. Jan 2009 08:53

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von cherry
Zitat:

Zitat von nahpets
Du greifst auf eine Datenbank zu, läuft die zufällig auf dem gleichen Rechner?

Ne, die MSSQL Datenbank läuft auf einem Server.

Zitat:

Zitat von franktron
Greift
Delphi-Quellcode: markieren
UpdateUserInfo(Username, false);
auf eine DB zu, wenn ja dann musst du die Abhängigkeiten für diesen Dienst änder.

Ja tut es. Was für Abhängigkeiten meinst du? -Wie soll ich das realisieren...

Zitat:

Zitat von nahpets
Da Du eine Methode zum Loggen hast, schreib da mal etwas mehr mit in die Logdatei, z. B. vor jeden Funktions- bzw. Prozeduraufruf ala...

Ok, da auch Ihr auf den ersten Blick keinen Fehler sieht, werde ich das Problem so mal probieren einzugrenzen.

Was die Abhängigkeiten betrifft:
Nutzt Dein Dienst irgendwelche Daten (Dateien, Datenbanken, Server, Services...), die auf dem gleichen Rechner laufen? Wenn ja, musst Du sicherstellen, dass Dein Dienst vor den Anderen beendet wird. Die Datenbank dürfte hier jedoch schonmal nicht das Problem sein (da auf anderem Server).
Was macht z. B. ScanAndWriteToDB und mit wem unterhält sich TCPClient.IOHandler.WriteLn(IntToStr(CmdScanFinish ed))?
Sind das Sachen auf dem Rechner mit dem Dienst oder greifst Du auf andere Systeme zu?
Wer wird mit Connect angesprochen?

Dienstabhängigkeit einrichten unter Windows 2003 siehe hier:http://techpubs.borland.com/starteam...readme_de.html und auf der Seite nach "Dienstabhängigkeit" suchen.

cherry 15. Jan 2009 10:27

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von nahpets
Was die Abhängigkeiten betrifft:
Nutzt Dein Dienst irgendwelche Daten (Dateien, Datenbanken, Server, Services...), die auf dem gleichen Rechner laufen? Wenn ja, musst Du sicherstellen, dass Dein Dienst vor den Anderen beendet wird.

...Was macht z. B. ScanAndWriteToDB und mit wem unterhält sich TCPClient.IOHandler.WriteLn(IntToStr(CmdScanFinish ed))? ...

Naja, mein Dienst greifft auf folgende Ressourcen zu:

Lokal:
- Logfile auf "C:\Programme\MeinDienst\Logfile.log"
- Prozeduren die auf Lokale Dateien zugreiffen (nur Lesen) {ScanAndWriteToDB}
- Prozeduren die Registry Keys lesen (nur lesen)
- Prozedur die angemeldeten Benutzer ausliest

Extern:
- MSSQL DB {ScanAndWriteToDB}
- Auswertungsprogramm das von einem anderen Rechner aus läuft {TCP/IP}

Zitat:

Zitat von nahpets
Dienstabhängigkeit einrichten unter Windows 2003 siehe hier:http://techpubs.borland.com/starteam...readme_de.html und auf der Seite nach "Dienstabhängigkeit" suchen.

Ich werde mir das mal anschauen

Dezipaitor 15. Jan 2009 11:04

Re: Eigener Dienst beendet nicht korrekt...
 
ServiceShutdown wird nur aufgerufen, wenn der Dienst von außen beendet werden soll, aber nicht wenn er sich beendet.
In ServiceShutdown musst du deine Prozedur ServiceExecute veranlassen aus der while-Schleife zu springen.
Dann kannst du am Ende von ServiceExecute dein Logging machen.

Es sieht so aus, als ob es nur deshalb manchmal geht, weil Windows deinen Dienst abschießt, da er nicht schnell genug aus ServiceExecute austritt. Ich sehe nämlich garkein Endbedingung.

nahpets 15. Jan 2009 11:45

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,

verschieb mal Deine Methode
Delphi-Quellcode:
procedure TMeinDienst.ServiceShutdown(Sender: TService);
begin
  UpdateUserInfo(Username, false);
  LogFile.LOG(msg0009);
end;
nach
Delphi-Quellcode:
procedure TMeinDienst.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  UpdateUserInfo(Username, false);
  LogFile.LOG(msg0009);
  Stopped := True;
end;

cherry 15. Jan 2009 12:50

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von nahpets
Hallo,

verschieb mal Deine Methode
Delphi-Quellcode:
procedure TMeinDienst.ServiceShutdown(Sender: TService);
begin
  UpdateUserInfo(Username, false);
  LogFile.LOG(msg0009);
end;
nach
Delphi-Quellcode:
procedure TMeinDienst.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  UpdateUserInfo(Username, false);
  LogFile.LOG(msg0009);
  Stopped := True;
end;

an dem kanns leider nicht liegen, da ich das schon von anfang an auch dort implementiert habe!

Zitat:

Zitat von Dezipaitor
ServiceShutdown wird nur aufgerufen, wenn der Dienst von außen beendet werden soll, aber nicht wenn er sich beendet.
In ServiceShutdown musst du deine Prozedur ServiceExecute veranlassen aus der while-Schleife zu springen.
Dann kannst du am Ende von ServiceExecute dein Logging machen.

Es sieht so aus, als ob es nur deshalb manchmal geht, weil Windows deinen Dienst abschießt, da er nicht schnell genug aus ServiceExecute austritt. Ich sehe nämlich garkein Endbedingung.

Das probiere ich gleich mal aus...

Angel4585 15. Jan 2009 12:54

Re: Eigener Dienst beendet nicht korrekt...
 
hast du das da:

ServiceThread.ProcessRequests(False);

schonmal so hingeschrieben:

ServiceThread.ProcessRequests(True);

?

Edit: Ah ne das war ja was anderes -.-

Wie wäre es mit debuggen? Aus der IDE mit dem prozess verbinden und dann schauen was wo wie hängt

cherry 15. Jan 2009 13:31

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von Dezipaitor
ServiceShutdown wird nur aufgerufen, wenn der Dienst von außen beendet werden soll, aber nicht wenn er sich beendet.
In ServiceShutdown musst du deine Prozedur ServiceExecute veranlassen aus der while-Schleife zu springen.
Dann kannst du am Ende von ServiceExecute dein Logging machen.

Es sieht so aus, als ob es nur deshalb manchmal geht, weil Windows deinen Dienst abschießt, da er nicht schnell genug aus ServiceExecute austritt. Ich sehe nämlich garkein Endbedingung.

ich hab mir mal das logfile angeschaut und dabei ist mir etwas aufgefallen:

Delphi-Quellcode:
2009-01-09 08:20:59 logfile created!
2009-01-09 08:20:59 Service successfully installed
2009-01-09 08:21:06 [administrator] logged in with IPAddress: 172.16.4.73
2009-01-09 08:21:06 [administrator] wrote "fast" logon info into database.
2009-01-09 08:21:26 [administrator] logged off

2009-01-09 08:23:05 [th21403] logged in with IPAddress: 172.16.4.73
2009-01-09 08:23:05 [th21403] wrote "full" logon info into database
2009-01-09 08:23:06 [th21403] 1 scan(s) has been automatically deleted!
2009-01-09 08:32:29 [th21403] logged off

2009-01-09 08:32:41 [ad_th21403] logged in with IPAddress: 172.16.4.73
2009-01-09 08:32:41 [ad_th21403] wrote "full" logon info into database
2009-01-09 08:35:32 [ad_th21403] logged off

2009-01-09 08:35:55 [ad_th21411] logged in with IPAddress: 172.16.4.73
2009-01-09 08:35:55 [ad_th21411] wrote "full" logon info into database
2009-01-09 08:37:51 [ad_th21411] logged off

2009-01-09 08:38:07 [th21403] logged in with IPAddress: 172.16.4.73
2009-01-09 08:38:07 [th21403] wrote "full" logon info into database
2009-01-09 08:38:07 [th21403] 1 scan(s) has been automatically deleted!
2009-01-09 08:39:09 [th21403] logged off

2009-01-09 08:39:11 [] Service shutdown

2009-01-09 09:10:35 [th21403] logged in with IPAddress: 172.16.4.73
2009-01-09 09:10:36 [th21403] wrote "full" logon info into database
2009-01-09 09:10:36 [th21403] 1 scan(s) has been automatically deleted!
2009-01-09 17:19:36 [th21403] logged off

2009-01-09 17:19:37 [] Service shutdown

2009-01-12 06:55:59 [th21403] logged in with IPAddress: 172.16.4.73
2009-01-12 06:56:01 [th21403] wrote "full" logon info into database
2009-01-12 06:56:01 [th21403] 1 scan(s) has been automatically deleted!
2009-01-12 15:58:19 [th21403] logged off

2009-01-12 15:58:20 [] Service shutdown

2009-01-13 06:54:55 [th21403] logged in with IPAddress: 172.16.4.73
2009-01-13 06:54:57 [th21403] wrote "full" logon info into database
2009-01-13 06:54:57 [th21403] 1 scan(s) has been automatically deleted!
2009-01-13 17:16:44 [th21403] logged off

2009-01-13 17:16:45 [] Service shutdown
und zwar ist mit aufgefallen, dass nur teilweise "[] Service shutdown" erscheint...
erscheint jetzt das nur wenn der dienst von windows abgewürgt wurde?

trotzdem erhalte ich immer ein "logged off" was eigentlich bedeutet, dass das logoff erfolgreich geschrieben wurde,
ist aber trotzdem nicht immer der Fall?!

nahpets 15. Jan 2009 13:44

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,

Zitat:

Zitat von Delphihilfe
Das Ereignis OnShutdown tritt ein, wenn das System, auf dem die Dienstanwendung läuft, heruntergefahren wird.

Das Ereignis OnStop tritt ein, wenn der Dienst vom Service Control Manager angehalten wird.

Zweite Variante entspricht net stop von der Console.

cherry 15. Jan 2009 15:29

Re: Eigener Dienst beendet nicht korrekt...
 
Ich hab jetzt mal eingebaut das Service Execute beendet wird wenn "onStop" oder "onShutdown" eintrifft. Das sieht aber ziemlich unschön aus, ist das wirklich die Lösung?

- bei meinen bisherigen Tests wurde zumindest bis jetzt das LogOout immer gemacht...
- leider kommt es manchmal zu einem Fehler wenn ich per net stop den Dienst beende... aber ich konnte nicht lokalisieren an
welcher stelle abgebrochen wird, trotz meiner {$IFDEF VERBOSE} ergänzung -> denn wenn die Meldung "Dienst konnte nicht beendet werden" kommt, wurde keine einzige meldung im log gemacht ab dem Zeitpunkt wo ich net stop eingebe...

Delphi-Quellcode:
procedure TMeinDienst.ServiceExecute(Sender: TService);
begin
  //ShowMessage('OnExecute - begin');
  while not Terminated do
  begin
    TRY
      // try to catch a user
      {$IFDEF VERBOSE}LogFile.Log(msg0049+'- in try block');{$ENDIF}
      if ShutDownNow then Exit;
      if Username <> '' then
      begin
        // AUTOSCAN
        // THIS SECTION IS FOR USER WHO JUST LOGGED IN
        if (Username <> GetSession) or (Welcome = False) then
        begin
          if ShutDownNow then Exit;
          {$IFDEF VERBOSE}LogFile.Log(msg0049+'before change username');{$ENDIF}
          ChangeUser;
          {$IFDEF VERBOSE}LogFile.Log(msg0049+'after change username');{$ENDIF}
          if Username <> '' then // its important to get sure that the username has really been catched
          begin
            if ShutDownNow then Exit;
            {$IFDEF VERBOSE}LogFile.Log(msg0049+'username is not equal to ""');{$ENDIF}
            Welcome := True;
            LogFile.Log(msg0004+GetIPAddress);
            // check if the user already exists in the database
            CheckDBforUser(ADOQuery1,ADOStoredProc1);
            if ShutDownNow then Exit;
            // Save to database that the user is logged in
            UpdateUserInfo(Username, true);
            if ShutDownNow then Exit;
            // get all info from User Table "t_bb_user"
            ADOQuery3.Close;
            ADOQuery3.Parameters.ParamValues['@username'] := username;
            ADOQuery3.Open;
            if ShutDownNow then Exit;
            {$IFDEF VERBOSE}LogFile.Log(msg0049+'passed cdfu and uui');{$ENDIF}
            // If the logged in user is not on the blacklist it will autoscan now
            if CheckUserOnBlacklist(Username) = False then
            begin
              if ShutDownNow then Exit;
              // autostart scan now, but first get defined scan_type from db!
              case ADOQuery3scan_type.AsInteger of
                0: begin ScanAndWriteToDB(True, stNoScanNoWrite); end;
                1: begin ScanAndWriteToDB(True, stFullScanWriteJustRootFoldersSize); end;
                2: begin ScanAndWriteToDB(True, stFullScanAndWrite); end;
              end;
            end
            else
            begin
              if ShutDownNow then Exit;
              // user is on blacklist, but login info will be saved
              ScanAndWriteToDB(True, stNoScanNoWrite);
              LogFile.Log(Username+msg0016);
            end;

            {$IFDEF VERBOSE}LogFile.Log(msg0049+'blacklist checked');{$ENDIF}

            // activate TCP server
            if ShutDownNow then Exit;
            if not assigned(TCPServer) then
              ActivateTCPServer;

          end;
        end
        else if StartManScan then
        begin
          {$IFDEF VERBOSE}LogFile.Log(msg0049+'man scan started');{$ENDIF}
          try
            // check if the user already exists in the database, else it will create him
            if Username <> '' then
            begin
              if ShutDownNow then Exit;
              CheckDBforUser(ADOQuery1,ADOStoredProc1);
              if ShutDownNow then Exit;
              ScanAndWriteToDB(False, stFullScanAndWrite);
              if ShutDownNow then Exit;
            end;
          finally
            // its very important to reset the variable StartManScan
            StartManScan := False;
            // send to the requesting host that the scan is complete now...
            Connect;
            TCPClient.IOHandler.WriteLn(IntToStr(CmdScanFinished));
            // disconnect
            Disconnect;
          end;
          if ShutDownNow then Exit;
        end;
      end
      else
      begin
        {$IFDEF VERBOSE}LogFile.Log(msg0049+'username ');{$ENDIF}
        if ShutDownNow then Exit;
        ChangeUser;
        Welcome := False;
      end;
    EXCEPT
      on e:Exception do
      begin
        LogFile.LOG(msg0000+e.Message);
        // maby there are some tcp actions pending...
        Disconnect;
        if fulllog then LogFile.Log(msg0039);
      end;
    END;
      ServiceThread.ProcessRequests(False);
      if ShutDownNow then Exit;
      {$IFDEF VERBOSE}LogFile.Log(msg0049+'BEGIN SLEEP');{$ENDIF}
      Sleep(1000);
      {$IFDEF VERBOSE}LogFile.Log(msg0049+'END SLEEP');{$ENDIF}
      if ShutDownNow then Exit;
  end;
  //ShowMessage('OnExecute - end');
end;
Ich denke das hat so gar nichts bewirkt... das Problem scheint, so denke ich, immer noch dies zu sein:

Zitat:

Zitat von Dezipaitor
ServiceShutdown wird nur aufgerufen, wenn der Dienst von außen beendet werden soll, aber nicht wenn er sich beendet.
In ServiceShutdown musst du deine Prozedur ServiceExecute veranlassen aus der while-Schleife zu springen.
Dann kannst du am Ende von ServiceExecute dein Logging machen.

Es sieht so aus, als ob es nur deshalb manchmal geht, weil Windows deinen Dienst abschießt, da er nicht schnell genug aus ServiceExecute austritt. Ich sehe nämlich garkein Endbedingung.

Und ich weiss nicht wie ich das nun machen soll.... ?!

nahpets 15. Jan 2009 16:22

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,

in der Delphihilfe heißt es im Beispiel:
Delphi-Quellcode:
while not Terminated do begin
**ServiceThread.ProcessRequests(True);
end;
bei Dir jedoch
Delphi-Quellcode:
  ServiceThread.ProcessRequests(False);
Habe gerade meine 3einhalb Service durchgeschaut, bei mir heißt's immer
Delphi-Quellcode:
ServiceThread.ProcessRequests(True)
und die verhalten sich (nach meinem Dafürhalten) alle ordentlich. Versuch' es doch bitte mal damit.
Zitat:

Zitat von Delphihilfe
VCL-Referenz
ProcessRequests (Methode von TServiceThread)

TServiceThread Methoden Siehe auch

Ermöglicht es Clients, den Dienst aufzurufen, der mit einem bestimmten Thread verknüpft ist.

Delphi-Syntax:

procedure ProcessRequests(WaitForMessage: Boolean);

C++ Syntax:

void __fastcall ProcessRequests(bool WaitForMessage);

Beschreibung

Die Methode ProcessRequests von TServiceThread wird in der Methode Execute aufgerufen, nachdem jede Ausführung der Ereignisbehandlungsroutine für OnExecute eines zugehörigen Dienstes beendet ist. Im Entwicklerhandbuch finden Sie weitere Informationen darüber, wie sich die Dienstausführung durch Abspaltung einzelner Threads für jede Dienstanforderung optimieren läßt.

Verstehe ich das richtig, dass bei ServiceThread.ProcessRequests(False) keine Messages abgearbeitet werden? Wenn dem so ist, warum darf Dein Service die Messages nicht abarbeiten? Wie erfährt er, dass er beendet werden soll oder dass das Betriebssystem herunter gefahren wird?

cherry 16. Feb 2009 09:31

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von nahpets

bei Dir jedoch
Delphi-Quellcode:
  ServiceThread.ProcessRequests(False);
Verstehe ich das richtig, dass bei ServiceThread.ProcessRequests(False) keine Messages abgearbeitet werden? Wenn dem so ist, warum darf Dein Service die Messages nicht abarbeiten? Wie erfährt er, dass er beendet werden soll oder dass das Betriebssystem herunter gefahren wird?

Wie genau das funktioniert weiss ich leider auch nicht, Tatsache ist aber, dass wenn ich True übergebe, der Dienst an dieser Stelle stehen bleibt und wahrscheinlich eine Message abwartet die er aber nicht erhält.

Die OnExecute Prozedur soll ja immer wieder ausgeführt werden, desshalb ist dort ja auch eine While Schliefe und ein Sleep(1000)
drin.

Oder mach ich dort grundsätzlich was falsch?

cherry 16. Feb 2009 09:43

Re: Eigener Dienst beendet nicht korrekt...
 
Hmm... Ich habs jetzt probeweise so gemacht:


Delphi-Quellcode:
ServiceThread.ProcessRequests(IsShuttingDownNow);

Die Variable IsShuttingDownNow ist von Anfang an auf False und wird dann in den Ereignissen
OnStop und OnShutdown auf True gesetzt.

Ist das richtig so?!

Angel4585 16. Feb 2009 10:28

Re: Eigener Dienst beendet nicht korrekt...
 
Wenn ich das recht verstehe ist das so:

ServiceThread.ProcessRequests(True); => Der Dienst wartet an dieser Stelle bis Messages da sind und bearbeitet diese dann
ServiceThread.ProcessRequests(False); => Der Dienst verarbeitet Messages, wenn keine da sind macht er einfach weiter

cherry 18. Feb 2009 14:14

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von Angel4585
Wenn ich das recht verstehe ist das so:

ServiceThread.ProcessRequests(True); => Der Dienst wartet an dieser Stelle bis Messages da sind und bearbeitet diese dann
ServiceThread.ProcessRequests(False); => Der Dienst verarbeitet Messages, wenn keine da sind macht er einfach weiter

Dann bist du mit meinem obigen Beitrag auch einverstanden?

Angel4585 18. Feb 2009 14:27

Re: Eigener Dienst beendet nicht korrekt...
 
ich würde die nicht auf true setzen.

meine Dienste sehen idR so aus:

Delphi-Quellcode:
procedure TMyDienst.Execute;
begin
while not terminated do
  begin
  //Irgendwas machen
  ServiceThread.ProcessRequests(False);
  end;
end;
OnShutdown usw belege ich erstmal garnicht.
Versuche dich mal ranzutasten wo bei dir das Problem liegt, also ein Minidienst machen und dann Stück für Stück einfügen und immerwieder zwischendurch testen obs geht

cherry 18. Feb 2009 14:32

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von Angel4585
OnShutdown usw belege ich erstmal garnicht.
Versuche dich mal ranzutasten wo bei dir das Problem liegt, also ein Minidienst machen und dann Stück für Stück einfügen und immerwieder zwischendurch testen obs geht

Tja da ist der Zug wohl abgefahren, mein Dienst umfasst nun bereits mehr als 1500 Zeilen Code und ist eingentlich so gut wie fertig. Ich habe den "Fehler" erst beim Testen bemerkt.

Beim starten des Dienst schreibt er in die Datenbank das er nun "online" ist.
Beim Beenden schreibt er in die Datenbank das er nicht mehr "online" ist...

Bis jetzt hatte ich ja eben auch immer auf False, aber dann schrieb er mir das LogOut manchmal nicht in die Datenbank.

hmm ich teste mal und meld mich dann mit meinen Ergebnissen wieder...

cherry 27. Apr 2009 10:15

Re: Eigener Dienst beendet nicht korrekt...
 
Leider funktioniert die Geschichte immer noch nicht 100% ig...

Zitat:

Zitat von Angel4585
ich würde die nicht auf true setzen.

meine Dienste sehen idR so aus:

Delphi-Quellcode:
procedure TMyDienst.Execute;
begin
while not terminated do
  begin
  //Irgendwas machen
  ServiceThread.ProcessRequests(False);
  end;
end;

kann es sein, dass wenn das "//irgendwas machen" etwas lange dauert, dass der Dienst dann die Message (shutdown) zu spät erhält und desshalb nicht richtig beendet?

wenn ja, was kann ich dagegen tun?

es kann schon mal sein, dass der Dienst irgendwelche scans durchführt oder in die DB schreibt und mehr als 20-30 sekunden daran arbeitet...

Angel4585 27. Apr 2009 11:13

Re: Eigener Dienst beendet nicht korrekt...
 
klar es wird das ausgeführt was du schreibst.
Wenn du dem Sienst sagst er soll das alles ausführen und zwischendurch nich zum beenden prüfen dauerts ne weile...
versuch mal den Teil auszulassen um zu schauen obs generell funktioniert

cherry 27. Apr 2009 11:26

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von Angel4585
versuch mal den Teil auszulassen um zu schauen obs generell funktioniert

hmm... genau wie ichs vermutet habe...

Delphi-Quellcode:
while not terminated do
begin
  ServiceThread.ProcessRequests(False);
  Sleep(500); // halbe sek. warten
end;
funktioniert einwandfrei... beendet immer korrekt
aaaaber:

Delphi-Quellcode:
while not terminated do
begin
  ServiceThread.ProcessRequests(False);
  Sleep(15000); // 15 sek. warten
end;
beendet nie korrekt...
Das bedeutet: Mein Dienst beendet korrekt, wenn er im gegebenen Zeitraum (von windows festgelegtes timeout) "ServiceThread.ProcessRequests" passiert, ansonsten schmiert er sozusagen ab!

Nun jetzt wissen wir wo das Problem ist...
aber wie löse ich das nun...

Ich will ja die Aktionen noch beenden bevor der dienst sich verabschiedet... kann ich nicht sagen: Hey, du olles System warte gefälligst bis mein dienst korrekt heruntergefahren wurde...

nahpets 27. Apr 2009 13:06

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,

das was Du da beschreibst sieht mir schwer nach Timeoutproblemen aus.

Kläre bitte zuerst, was Dein Dienst alles an "Fremdem" benötigt. Versuche dann in der Dienstekonfiguration diese Abhängigkeiten zu berücksichtigen, damit Dein Dienst vor den anderen, benötigten Diensten runtergefahren wird. Laufen Datenbank... auf dem gleichen Rechner als Dienste? Dann musst Du die Reihenfolge beim Starten und Beenden berücksichtigen.
Ist der Dienst abhängig von anderen Programmen, die nicht als Dienst laufen, dann dürfte es schwierig werden, die Abhängigkeiten in den Griff zu bekommen.

Wenn Dein Dienst mal 20-30 Sekunden "irgendwas" macht und dazwischen der Rechner runter gefahren wird bzw. der Dienst gestoppt wird, bist Du vermutlich in Bezug auf Timeoutzeiten jenseits von Gut und Böse. Kannst Du die langen "Arbeitsschleifen" irgendwie ohne Datenverlust auf kleiner Happen verteilen?

Ein Dienst hat ja diverse Ereignisse, Start, Stop, Pause, Shutdown ... . Kannst Du Dir dort irgendwie ein globales Flag setzen, auf das Deine Langläuferroutinen ggfls. reagieren, um ihre Arbeit abzubrechen?

Was macht der Dienst, wenn er für 20-30 Sekunen "On Tour" ist. Wird das timerabhängig gesteuert. Hätten kürzere Timerintervalle auch kürzere Bearbeitungszeiten zur Folge. Dann wäre ggfls. ein "mach öfter weniger" eine Lösungsansatz.

Damit das Betriebssystem merkt, ob Dein Dienst läuft, muss der auf jeden Fall reagieren und darf nicht "beliebig" lange vor sich hin wurschteln. Zugegeben weiß ich momentan keine Antwort auf die Frage: "Hey, du..."

cherry 30. Apr 2009 08:09

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von nahpets
Hallo,
Kläre bitte zuerst, was Dein Dienst alles an "Fremdem" benötigt. Versuche dann in der Dienstekonfiguration diese Abhängigkeiten zu berücksichtigen, damit Dein Dienst vor den anderen, benötigten Diensten runtergefahren wird. Laufen Datenbank... auf dem gleichen Rechner als Dienste? Dann musst Du die Reihenfolge beim Starten und Beenden berücksichtigen. Ist der Dienst abhängig von anderen Programmen, die nicht als Dienst laufen, dann dürfte es schwierig werden, die Abhängigkeiten in den Griff zu bekommen.

Mein Dienst benötigt keine Fremdprogramme und keine anderen Dienste, naja, ausser dass ich per ADO auf einen SQL-Server (nicht auf meinem Computer) zugreiffe.
Braucht ADO da noch was ?

Zitat:

Zitat von nahpets
Wenn Dein Dienst mal 20-30 Sekunden "irgendwas" macht und dazwischen der Rechner runter gefahren wird bzw. der Dienst gestoppt wird, bist Du vermutlich in Bezug auf Timeoutzeiten jenseits von Gut und Böse. Kannst Du die langen "Arbeitsschleifen" irgendwie ohne Datenverlust auf kleiner Happen verteilen?

Das wird sehr schwierig. Da das was etwas länger gehen könnte eine for- schleife ist die in die Datenbank schreibt...

Zitat:

Zitat von nahpets
Ein Dienst hat ja diverse Ereignisse, Start, Stop, Pause, Shutdown ... . Kannst Du Dir dort irgendwie ein globales Flag setzen, auf das Deine Langläuferroutinen ggfls. reagieren, um ihre Arbeit abzubrechen?

Ich wüsste nicht wie ich das anstellen sollte. soll ich denn in meiner OnExecute Procedure immer wieder nach diesem flag fragen und allenfalls exiten?
das wäre doch kein schöner code;

Zitat:

Zitat von nahpets
Was macht der Dienst, wenn er für 20-30 Sekunen "On Tour" ist. Wird das timerabhängig gesteuert. Hätten kürzere Timerintervalle auch kürzere Bearbeitungszeiten zur Folge. Dann wäre ggfls. ein "mach öfter weniger" eine Lösungsansatz.

Da das was etwas länger gehen könnte eine for- schleife ist die in die Datenbank schreibt...

Zitat:

Zitat von nahpets
Damit das Betriebssystem merkt, ob Dein Dienst läuft, muss der auf jeden Fall reagieren und darf nicht "beliebig" lange vor sich hin wurschteln. Zugegeben weiß ich momentan keine Antwort auf die Frage: "Hey, du..."

Und wenn ich in meinem On execute nichts stehen hätte als folgendes:

Delphi-Quellcode:
while not terminated do
begin
  if dienststoppen then
  begin
    TerminateThread(...);
    TerminateThread(...);
    TerminateThread(...);
  end;
  ServiceThread.ProcessRequests(False);
  Sleep(500); // halbe sek. warten
end;
und dann alle aktionen in eigenen threads? ware das eine Idee?

Wie habt ihr das bei euren diensten gemacht? habt ihr da immer nur kleine Aktionen drin die nie länger dauern als 10 sek?
Ich bin am verzweifeln... heul :wall:

nahpets 30. Apr 2009 09:04

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,

mit dem Abbruch der For-Schleife hatte ich mir in dieser Form vorgestellt:
Delphi-Quellcode:
unit SVReplikationUnit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
  DB, ADODB, ExtCtrls, Registry, StrUtils;

type
  TReplikator = class(TService)
    tm: TSpecialTimer;
    acABC: TADOConnection;
    acBN: TADOConnection;
    qryBN: TADOQuery;
    qryABC: TADOQuery;
    qryBNMaxUhrzeit: TADOQuery;
    qryABCMaxUhrzeit: TADOQuery;
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceExecute(Sender: TService);
    procedure tmTimer(Sender: TObject);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServicePause(Sender: TService; var Paused: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
    procedure ServiceContinue(Sender: TService; var Continued: Boolean);
    procedure ServiceShutdown(Sender: TService);
    procedure ServiceBeforeInstall(Sender: TService);
    procedure ServiceAfterUninstall(Sender: TService);
  private
    { Private-Deklarationen }
  public
    function GetServiceController: TServiceController; override;
    { Public-Deklarationen }
    bShutDownOrStopOrPause : Boolean;
  end;

var
  TReplikatorReplikator: TReplikator;

implementation

{$R *.DFM}

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  TReplikatorReplikator.Controller(CtrlCode);
end;

function TReplikator.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TReplikator.ServiceCreate(Sender: TObject);
begin
  // ShortDateFormat := 'yyyy-mm-dd'; // Darf nicht gesetzt werden, da auch die Datenbankinhalte übersetzt werden.
  ThousandSeparator := ','; // Muss gesetzt werden, da die Datenbank Komma erwartet.
  DecimalSeparator := '.'; // Muss gesetzt werden, da die Datenbank Punkt erwartet.
  bShutDownOrStopOrPause := False;
end;

procedure TReplikator.ServiceExecute(Sender: TService);
begin
  while not Terminated do ServiceThread.ProcessRequests(True);
end;

procedure TReplikator.tmTimer(Sender: TObject);
Var
          i : Integer;
begin
  tm.Enabled := False;
  // Hier passiert so allerhand, was auch 'ne Weile dauern kann.
  For i := 0 to MaxInt do begin
    // Ist der Abbruchschalter gesetzt, dann aufhören.
    // if i Mod 100 = 0 then // wenn nicht bei jedem Schleifendurchlauf geprüft werden soll.
    if bShutDownOrStopOrPause then Break;
  end;
  tm.Enabled := True;
end;

procedure TReplikator.ServiceStart(Sender: TService; var Started: Boolean);
Var
          iOffset : Integer;
begin
  tm.Enabled := True;
  bShutDownOrStopOrPause := False;
end;

procedure TReplikator.ServicePause(Sender: TService; var Paused: Boolean);
begin
  tm.Enabled := False;
  bShutDownOrStopOrPause := True;
end;

procedure TReplikator.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  tm.Enabled := False;
  bShutDownOrStopOrPause := True;
end;

procedure TReplikator.ServiceContinue(Sender: TService; var Continued: Boolean);
Var
          iOffset : Integer;
begin
  tm.Enabled := True;
  bShutDownOrStopOrPause := False;
end;

procedure TReplikator.ServiceShutdown(Sender: TService);
begin
  tm.Enabled            := False;
  bShutDownOrStopOrPause := True;
end;

// Messagefile registrieren
procedure TReplikator.ServiceBeforeInstall(Sender: TService);
Var
    Reg : TRegistry;
begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  Reg.OpenKey('system\CurrentControlSet\Services\EventLog\Application\' + Self.Name,True);
  Reg.WriteString('EventMessageFile',ParamStr(0));
  Reg.WriteInteger('TypesSupported',7);
  Reg.CloseKey;
  Reg.OpenKey('system\CurrentControlSet\Services\TReplikator\' + Self.Name,True);
  Reg.WriteString('Description','Repliziert die Daten zwischen den Datenbanken ABC und BN');
  Reg.CloseKey;
  Reg.Free;
end;

// Messagefile aus Registrierung entfernen
procedure TReplikator.ServiceAfterUninstall(Sender: TService);
Var
    Reg : TRegistry;
begin
  Reg := TRegistry.Create;
  Reg.RootKey := HKEY_LOCAL_MACHINE;
  Reg.DeleteKey('system\CurrentControlSet\Services\EventLog\Application\' + Self.Name);
  Reg.DeleteKey('system\CurrentControlSet\Services\TReplikatorReplikator\' + Self.Name);
  Reg.CloseKey;
  Reg.Free;
end;

end.
Das ist nicht getestet, sondern nur schnell aus einem vorhandenen Service zusammengedaddelt. Hoffe trotzdem, dass es Dir bei der Problemlösung weiterhilft.

cherry 30. Apr 2009 09:17

Re: Eigener Dienst beendet nicht korrekt...
 
hmmm...

du hast im service execute eigentlich nicht viel drin, du regelst alles mit einem timer. Ist das die bessere lösung im allgemeinen.
Denn so wird ja wenigstens immer wieder ServiceThread.ProcessRequests(True); abgefragt..

und bei dir steht da auch true, also er soll auf eine message warten...
vielleicht müsste ich meinen dienst mal mit timer realisieren?!

nahpets 30. Apr 2009 09:34

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,
Zitat:

Zitat von cherry
hmmm...

du hast im service execute eigentlich nicht viel drin, du regelst alles mit einem timer. Ist das die bessere lösung im allgemeinen.
Denn so wird ja wenigstens immer wieder ServiceThread.ProcessRequests(True); abgefragt..

und bei dir steht da auch true, also er soll auf eine message warten...
vielleicht müsste ich meinen dienst mal mit timer realisieren?!

den Timer nutze ich deshalb, weil dieser Dienst im Ursprung pünktlich zur vollen Stunde einen bestimmten Job ausführen sollte. Dafür habe ich mir einen Nachfahren von TTimer geschrieben, der beim Timer.Enable := True das Interval auf die Millisekunden bis zur nächsten vollen Stunde setzt. Aber das ist hier eigentlich nachrangig. Wann und wie oft soll denn Dein Dienst tätig werden. Dann könnte ein Timer durchaus die "richtige" Lösung sein. Ob's die bessere Lösung ist, weiß ich nicht, es war für das konkrete Problem die praktischste Lösung.

cherry 30. Apr 2009 09:40

Re: Eigener Dienst beendet nicht korrekt...
 
naja, bei dir ist jedenfalls gewährleistet, dass die messages immer abgefangen werden, mit ServiceThread.ProcessRequests(True);.
Dadurch kann bei dir ein solches Problem ja gar nicht bestehen.

Was hälts du den von meiner Thread Variante`?

Delphi-Quellcode:
while not terminated do
begin
  if dienststoppen then
  begin
    TerminateThread(...);
    TerminateThread(...);
    TerminateThread(...);
  end;
  ServiceThread.ProcessRequests(False);
  Sleep(500); // halbe sek. warten
end;
eigentlich ähnlich wie deine on Timer variante...
na?

nahpets 30. Apr 2009 11:21

Re: Eigener Dienst beendet nicht korrekt...
 
Hallo,

mit Threads kenne ich mich jetzt nicht wirklich aus. Es scheint aber so zu sein, dass der Timer einen neuen Thread aufmacht, da andere Dienste von mir mit mehreren Timern arbeiten und dadurch auch mehrere (sehr unterschiedliche) Aufgaben gleichzeitig erledigt werden. Es ist wohl eher Geschmacksache. Bei Deiner Variante werden die Threads wohl von außen gestoppt und Du musst sicherstellen, dass sie auf das Beenden auch zeitnah reagieren. Besteht da nicht eventuell die Gefahr, dass Du das Problem auf eine andere Stelle verschiebst, wenn gerade in einem Thread eine For-Schleife abgearbeitet wird. Ist da sichergestellt, das der Thread auch "mitten" in der For-Schleife beendet wird. Besteht da dann die Möglichkeit, dass inkonsistente Daten übrig bleiben?
Meine (subjektive) Meinung ist: Über einen Schalter kontrolliert aus einer Routine aussteigen, um noch eine bestehende Aufgabe abzuschließen. Du gehst ja im Prinzip her und beendest die Threads nacheinander. Der zweite Thread erfährt also erst nach dem erfolgreichen Beenden des ersten Threads, dass er sich beenden soll, der Dritte nach dem Zweiten.... (Oder läuft das intern parallel ab, sprich: wartet TerminateThread auf das Ende des Threads?) Hier müsstest Du also sicherstellen, dass das alles innerhalb der Timeoutzeit von Windows erfolgreich beendet wird. Nur den Schalter setzen und dann innerhalb der Threads den Schalter zu prüfen, könnte das Beenden (vermutlich) beschleunigen. Inwieweit es sinnvoll ist, aus Threads heraus auf globale Variabeln zuzugreifen, vermag ich nicht definitiv zu beantworten.

Bei einem anderen Dienst habe ich kürzlich (zufällig) festgestellt, dass Windows 30 Sekunden wartet, bevor es einen Dienst "mit der Keule" erschlägt.

cherry 30. Apr 2009 12:27

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von nahpets
Bei Deiner Variante werden die Threads wohl von außen gestoppt und Du musst sicherstellen, dass sie auf das Beenden auch zeitnah reagieren. Besteht da nicht eventuell die Gefahr, dass Du das Problem auf eine andere Stelle verschiebst, wenn gerade in einem Thread eine For-Schleife abgearbeitet wird. Ist da sichergestellt, das der Thread auch "mitten" in der For-Schleife beendet wird. Besteht da dann die Möglichkeit, dass inkonsistente Daten übrig bleiben?

das würde dann genau so sein... nur lieber da als anderswo ;-) vermeiden kann mann das ja sowieso nicht, dass gewisse aktionen inmitten unterbrochen werden müssen.

Zitat:

Zitat von nahpets
Meine (subjektive) Meinung ist: Über einen Schalter kontrolliert aus einer Routine aussteigen, um noch eine bestehende Aufgabe abzuschließen.

naja, irgendwie kann ich mich mit dieser methode auch nicht wirlklich anfreunden, ist irgendwie unschön. Diese Abfrage müsste dann ca. 30-Mal irgendwo in meinem Code stehen und da graut mir irgendwie davon. Nundenn, wenn das die Offizielle Lösung ist mache ich das gerne so. Ich würde aber auch noch gerne ein paar andere Meinungen hören, ich kann mir irgendwie nicht vorstellen, dass ich der Einzige bin der schon mal vor diesem Problem gestanden ist. :gruebel:

Zitat:

Zitat von nahpets
Du gehst ja im Prinzip her und beendest die Threads nacheinander. Der zweite Thread erfährt also erst nach dem erfolgreichen Beenden des ersten Threads, dass er sich beenden soll, der Dritte nach dem Zweiten....

TerminateThread teilt dem Betriebssystem mit, das der Thread beendet werden soll und kehrt dann zurück, von dem her sollte das eigentlich gehen...

Zitat:

Zitat von nahpets
Bei einem anderen Dienst habe ich kürzlich (zufällig) festgestellt, dass Windows 30 Sekunden wartet, bevor es einen Dienst "mit der Keule" erschlägt.

und wie hast du die Problematik anschliessend gelöst?

nahpets 30. Apr 2009 13:19

Re: Eigener Dienst beendet nicht korrekt...
 
Zitat:

Zitat von cherry
Zitat:

Zitat von nahpets
Meine (subjektive) Meinung ist: Über einen Schalter kontrolliert aus einer Routine aussteigen, um noch eine bestehende Aufgabe abzuschließen.

naja, irgendwie kann ich mich mit dieser methode auch nicht wirlklich anfreunden, ist irgendwie unschön. Diese Abfrage müsste dann ca. 30-Mal irgendwo in meinem Code stehen und da graut mir irgendwie davon. Nundenn, wenn das die Offizielle Lösung ist mache ich das gerne so. Ich würde aber auch noch gerne ein paar andere Meinungen hören, ich kann mir irgendwie nicht vorstellen, dass ich der Einzige bin der schon mal vor diesem Problem gestanden ist. :gruebel:

Ne, bist bestimmt nicht der Einzige aber vermutlich gibt es "die" Lösung nicht. Meine Lösung ist sicherlich nicht gerade elegant, wohl auch kaum als objektorientiert zu bezeichnen, brachte aber mit vertretbarem Aufwand die erwünschte Lösung. Aber das kommt dann sicherlich auf den Einzelfall an. Wenn Du so eine Lösung nur implementieren kannst mit einer Unmenge von zusätzlichen Abfragen, dann ist das bestenfalls als suboptimal zu bezeichnen.
Zitat:

Zitat von cherry
Zitat:

Zitat von nahpets
Du gehst ja im Prinzip her und beendest die Threads nacheinander. Der zweite Thread erfährt also erst nach dem erfolgreichen Beenden des ersten Threads, dass er sich beenden soll, der Dritte nach dem Zweiten....

TerminateThread teilt dem Betriebssystem mit, das der Thread beendet werden soll und kehrt dann zurück, von dem her sollte das eigentlich gehen...

D. h. aber, dass der Thread mehr oder weniger "unkontrolliert" beendet wird und ein Datenbankzugriff eventuell "mittendrin" abgebrochen wird. Es könnte also sein, dass Transaktionen weder mit Commit noch mit Rollback beendet werden? Stelle mir das immer so vor wie: Datenbankapplikation per Taskmanager beenden. Das ist etwas, das ich äußerst ungerne mache.
Zitat:

Zitat von cherry
Zitat:

Zitat von nahpets
Bei einem anderen Dienst habe ich kürzlich (zufällig) festgestellt, dass Windows 30 Sekunden wartet, bevor es einen Dienst "mit der Keule" erschlägt.

und wie hast du die Problematik anschliessend gelöst?

Garnicht, da war auf dem Rechner so Allerlei abgestürzt und hatte sich gegenseitig in die Knie gezwungen, habe nicht herausgefunden, was da die eigentliche Ursache des Problemes war. Vermutlich aber der Neustart eines anderen Servers, auf dessen Datenbanken zu diesem Zeitpunkt zugegriffen wurde.


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:35 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