Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Thread mit Timeout (https://www.delphipraxis.net/144825-thread-mit-timeout.html)

schwa226 17. Dez 2009 15:26


Thread mit Timeout
 
Hi,

ich möchte externe Programme starten. Dazu nimm ich die Funktion von hier im Board (ExecuteAndWait).
Wobei ich nicht warte sondern die Anwendung einfach starte.

Nun habe ich das in einen eigenen Thread ausgelagert.

D.h. wenn ich den Thread erzeuge führt dieser den Start des Programmes aus und beendet sich danach selber wieder.
Nun habe ich ein Problem wenn sich z.B. das Programm nicht starten lässt. Z.b. wenn eine Abfrage von Kaspersky kommt ob es gestartet werden darf.
Dann bleibt es in der ExecuteAndWait stehen und der Thread beendet sich nicht.

Kann man einem Thread einen Timeout mitgeben das er sich dann trotzdem nach 2 Sekunden selbst beendet - auch wenn das ausführen nicht erfolgreich war?

Astat 17. Dez 2009 16:05

Re: Thread mit Timeout
 
Hallo schwa226.

Zitat:

Zitat von schwa226
Kann man einem Thread einen Timeout mitgeben das er sich dann trotzdem nach 2 Sekunden selbst beendet - auch wenn das ausführen nicht erfolgreich war?

Nein, einen offiziellen Weg (in der Thread API integriert) gibt es da nicht.
Du musst selber im Code entscheiden wenn deine Abarbeitung beendet ist.
Verwende ein Sperrobject mit Timeot (WaitForSingleObject etc.)

lg. Astat

turboPASCAL 17. Dez 2009 16:15

Re: Thread mit Timeout
 
Zitat:

ich möchte externe Programme starten. Dazu nimm ich die Funktion von hier im Board (ExecuteAndWait).
Wobei ich nicht warte sondern die Anwendung einfach starte.
und warum nicht möchtest du nicht Delphi-Referenz durchsuchenShellExecute nutzen ? :gruebel:

schwa226 18. Dez 2009 06:41

Re: Thread mit Timeout
 
Ich benutze ja ShellExecute!

Aber es kann bei einem Fehler passieren das es in der Zeile:
Delphi-Quellcode:
Result := ShellExecuteExW(@ShExecInfoW);
hängen bleibt.

Werd mir das mit WaitForSingleObject mal ansehen!

Mein erster Versuch war einen Timer in den Thread einzubauen (wie bei einer DLL). Wenn der Timer auslöst sollte er den Thread abschießen.

Das klappt aber nicht so ganz, da der Thread ja auch Terminate nicht anspricht wenn er hängt.
Wie kann man einen Thread am besten zum Beenden zwingen?

schwa226 18. Dez 2009 11:13

Re: Thread mit Timeout
 
Keiner eine Info wie man einen hängenden Thread beenden kann ohne den Prozess beenden zu müssen?
:cry:

Reinhard Kern 18. Dez 2009 12:02

Re: Thread mit Timeout
 
Zitat:

Zitat von schwa226
Keiner eine Info wie man einen hängenden Thread beenden kann ohne den Prozess beenden zu müssen?
:cry:

Doch, sicher, von aussen: such nach kill thread und lass das Hauptprogramm den Thread überwachen. NUR: das ist kein "graceful shutdown", sondern entspricht dem Beenden durch Ctrl-Lt-Del mit allen möglichen Nebenwirkungen. Es kann ja auch logisch nicht anders sein. Es dürfte keine Möglichkeit geben, ein dabei verursachtes Memory Leak zu beseitigen.

Du kannst das ja dann a la MS regeln: "Dieses Programm hat einen Fehler gemacht und muss sich beenden".

Gruss Reinhard

Luckie 18. Dez 2009 12:51

Re: Thread mit Timeout
 
Zitat:

Zitat von Astat
Verwende ein Sperrobject mit Timeot (WaitForSingleObject etc.)

MSDN-Library durchsuchenWaitForSingleObjectTimeOut

Reinhard Kern 18. Dez 2009 16:08

Re: Thread mit Timeout
 
Zitat:

Zitat von Luckie
Zitat:

Zitat von Astat
Verwende ein Sperrobject mit Timeot (WaitForSingleObject etc.)

MSDN-Library durchsuchenWaitForSingleObjectTimeOut

Hallo,

schön und gut, aber das muss man dann in einem anderen thread aufrufen - wenn man Wait.. aufruft, wartet der thread ja nur. WaitForSingleObjectUndTuInzwischenWas gibt es meines Wissens nicht.

Der Link führt übrigens zu einer Fehlermeldung.

Gruss Reinhard

Astat 18. Dez 2009 22:38

Re: Thread mit Timeout
 
Hallo Reinhard Kern.

Zitat:

Zitat von Reinhard Kern
..,schön und gut, aber das muss man dann in einem anderen thread aufrufen - wenn man Wait.. aufruft, wartet der thread ja nur. WaitForSingleObjectUndTuInzwischenWas gibt es meines Wissens nicht.

Naja etwas kreativität sollte man schon hineinfliessen lassen.

Anbei ein Ansatz wie soetwas realisiert werden kann.

Delphi-Quellcode:
function StartPEFile(szFileName: PChar; Visibility: integer; szWorkDir: PChar;
  dwTimeOut: DWORD = 10000): integer;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  Result := -1;
  FillChar(StartupInfo, Sizeof(StartupInfo), 0);
  StartupInfo.cb := Sizeof(StartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := Visibility;

  if CreateProcess(
     nil,                          { pointer to command line string }
     szFileName,
     nil,                          { pointer to process security attributes }
     nil,                          { pointer to thread security attributes}
     false,                        { handle inheritance flag }
     CREATE_NEW_CONSOLE or         { creation flags }
     NORMAL_PRIORITY_CLASS,
     nil,                          { pointer to new environment block}
     szWorkDir,                    { pointer to current directory name }
     StartupInfo,                  { pointer to STARTUPINFO }
     ProcessInfo)                  { pointer to PROCESS_INF }
  then begin
    //-- Max Timeot warten bis Application MSQ gestartet hat.
    if WaitforInputIdle(ProcessInfo.hProcess, dwTimeOut) = 0 then
      //-- Ist en Errorcode vorhanden?
      GetExitCodeProcess(ProcessInfo.hProcess, DWORD(Result))
    else
       Result := -1;
    //-- ProcessInfo Struct kann auch global zwischengespeichert werden,
    //-- um nachträglich wieder auf die Application zuzuggreifen, bzw. zu steuern
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hProcess);
  end;
end;

function StarterThread(ptrData: Pointer): Integer;
begin
  if StartPEFile(PChar('c:\myProg.exe'), SW_SHOWNORMAl, nil) <> 0 then
    RaiseLastWin32Error;
end;

var
  _hStartThread, _dwServerThreadID: DWORD;
begin
  //-- Programm Asynchron Starten (StarterThread)
  //-- Eventuelle Startparameter können über Heap oder Stack ünergeben werden
  //-- Achtung Stackvariablen sind nach verlassen der Procedure nicht mehr gültig.
  //-- _hStartThread kann wenn notwendig auch eine Globale Threadliste usw. sein.
  //-- Damit ist es möglich nachträglich den Thread zu steuern
  _hStartThread := BeginThread(nil, 0, StarterThread, nil, 0 ,_dwServerThreadID);
end.
lg. Astat

Reinhard Kern 19. Dez 2009 00:07

Re: Thread mit Timeout
 
Hallo,

bist du sicher, dass das mit CREATE_NEW_CONSOLE funktioniert? Zitat aus MSDN:

"If this process is a console application or does not have a message queue, WaitForInputIdle returns immediately."

Ausserdem wird doch auch dabei der Prozess von "aussen" auf Timeout überwacht - war meine Rede seit 45.

Gruss Reinhard


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:54 Uhr.
Seite 1 von 2  1 2      

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