Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Default-Wert aus Funktion nach timeout (D6) (https://www.delphipraxis.net/201546-default-wert-aus-funktion-nach-timeout-d6.html)

myicq 31. Jul 2019 07:39

Default-Wert aus Funktion nach timeout (D6)
 
Hallo alle,

ich bin dabei eine Funktion zu schreiben das eine Wert über Netzwerk abfragt. Normalerweise geht das sehr schnell, weniger als 100 msec. Aber ich möchte nicht das mein Programm sich abhängt wenn zB die Verbindung geht.

Wie mache ich eine "Timeout" feature, das nach zB 1 Sek eine Default-Wert zurückgibt ?

Beispiel:
Delphi-Quellcode:
  // Demofunktion
  // wartet für immer, Fehler simulieren.
 function get_value: integer;
 begin
   while 1=1 do
     begin
       // wait..
       sleep(1);
     end;
 end;
Ich möchte gern get_value abrufen können, aber innerhalb zB 1 Sekunde eine Defaultwert zurück.

Ich bin unter Delphi6, und habe leider zu wenig Erfahrung mit TThreads gemacht (vermute Threads ist die Lösung ??). Deshalb wenn möglich (Triviales) komplettbeispiel ?

Danke für jeder Hilfe!

Uwe Raabe 31. Jul 2019 08:22

AW: Default-Wert aus Funktion nach timeout (D6)
 
Threads und Trivial gehen in der Regel nicht zusammen.

Rollo62 31. Jul 2019 08:25

AW: Default-Wert aus Funktion nach timeout (D6)
 
Hier zumindest mal ein sehr gutes Thread-Tutorial für den Anfang, von Daniel.

HolgerX 31. Jul 2019 08:30

AW: Default-Wert aus Funktion nach timeout (D6)
 
Hmm..

Zitat:

Zitat von myicq (Beitrag 1438435)
Hallo alle,

ich bin dabei eine Funktion zu schreiben das eine Wert über Netzwerk abfragt. Normalerweise geht das sehr schnell, weniger als 100 msec. Aber ich möchte nicht das mein Programm sich abhängt wenn zB die Verbindung geht.

Wie mache ich eine "Timeout" feature, das nach zB 1 Sek eine Default-Wert zurückgibt ?


Welche 'Netzwerkkomponente' (Indy, Socket..) verwendest Du denn für deine Abfrage?
Diese Komponenten haben i.R. einen eigenen TimeoutTimer, welcher einfach nur auf eine Sekunde reduziert werden müsste. Die Defaultwerte können deutlich höher sein..

Google mal mit dem ClassName und 'TimeOut' und Du wirst Beispiele finden.

Das ganze mit einem ordentlichen Try Except, bzw. Errorhandling der Komponente und beim Fehler kommt ein Defaultwert.

Der schöne Günther 31. Jul 2019 08:34

AW: Default-Wert aus Funktion nach timeout (D6)
 
Zitat:

Zitat von HolgerX (Beitrag 1438440)
Diese Komponenten haben i.R. einen eigenen TimeoutTimer, welcher einfach nur auf eine Sekunde reduziert werden müsste.

Aber auch bei weitem leider nicht überall. Es gibt Dinge bei denen man nicht kontrollieren kann wie lange sie maximal blockieren.


Viel einfacher wäre es, wenn die Lizenzbedingungen es zulassen, von einer bald 20 Jahre alten Entwicklungsumgebung auf etwas neueres zu wechseln das z.B. "Tasks" hat. Dann sieht es in Delphi nur noch so aus:

Delphi-Quellcode:
function TForm1.holeNetzwerkDaten(): Integer;
begin
   TThread.Sleep( Random(1000) );
   Result := 42;
end;

function TForm1.holeNetzwerkDaten(const timeoutMs: Word): Integer;
const
   standardWert: Integer = 99;
var
   future: IFuture<Integer>;
begin
   future := TTask.Future(
      function(): Integer
      begin
         Result := holeNetzwerkDaten();
      end
   );
   if future.Wait(timeoutMs) then
      Result := future.Value
   else
      begin
         future.Cancel();
         Result := standardWert;
      end;
end;
Könnte so einfach sein 😉

Rollo62 31. Jul 2019 08:40

AW: Default-Wert aus Funktion nach timeout (D6)
 
Ja, neuers Delphi würde auch mit Omnithread Library gehen.
http://www.omnithreadlibrary.com/boo...l#introduction

Da steht zwar bis runter zu D2007, könnte aber sein das auch Teile schon ab D6 funktionieren
(vielleicht hat da ja jemand hier Erfahrung ob das läuft).

peterbelow 31. Jul 2019 10:25

AW: Default-Wert aus Funktion nach timeout (D6)
 
Zitat:

Zitat von myicq (Beitrag 1438435)
Hallo alle,

ich bin dabei eine Funktion zu schreiben das eine Wert über Netzwerk abfragt. Normalerweise geht das sehr schnell, weniger als 100 msec. Aber ich möchte nicht das mein Programm sich abhängt wenn zB die Verbindung geht.

Wie mache ich eine "Timeout" feature, das nach zB 1 Sek eine Default-Wert zurückgibt ?

Beispiel:
Delphi-Quellcode:
  // Demofunktion
  // wartet für immer, Fehler simulieren.
 function get_value: integer;
 begin
   while 1=1 do
     begin
       // wait..
       sleep(1);
     end;
 end;
Ich möchte gern get_value abrufen können, aber innerhalb zB 1 Sekunde eine Defaultwert zurück.

Ich bin unter Delphi6, und habe leider zu wenig Erfahrung mit TThreads gemacht (vermute Threads ist die Lösung ??). Deshalb wenn möglich (Triviales) komplettbeispiel ?

Danke für jeder Hilfe!

Versuchs mal hiermit.

Delphi-Quellcode:
type
  TWorkthread = class(TTHread)
  strict private
    FValue: Integer;
  protected
    procedure Execute; override;
  public
    property Value: Integer read FValue;
  end;

procedure TWorkthread.Execute;
begin
  // code to get the data goes here
  // for now simulate a 10 second delay
  sleep(10000);
  FValue := 666;
end;

function get_value: integer;
const
  OneSecond = 1000;
  DefaultValue = 999;
var
  LResult: dword;
  LWorker : TWorkthread;
begin
  // thread starts running immediately
  LWorker := TWorkthread.Create;
  try
    LResult := WaitForSingleObject(LWorker.Handle, OneSecond);
    if LResult = WAIT_OBJECT_0 then
      Result := LWorker.Value
    else if LResult = WAIT_TIMEOUT then begin
      LWorker.FreeOnTerminate := true;
      LWorker := nil;
      //abandon the thread
      Result := DefaultValue;
    end
    else
      raise Exception.CreateFmt('Thread creation failed, wait result was $%x',[LResult]);
  finally
    LWorker.Free;
  end;
end;

HolgerX 31. Jul 2019 13:26

AW: Default-Wert aus Funktion nach timeout (D6)
 
Hmm..


Zitat:

Zitat von peterbelow (Beitrag 1438451)
Versuchs mal hiermit.


kleine Korrectur für D6 ;)

Delphi-Quellcode:
type
  TWorkthread = class(TTHread)
  private                        // Delphi 6 kennt noch kein strict
    FValue: Integer;
  protected
    procedure Execute; override;
  public
    property Value: Integer read FValue;
  end;

procedure TWorkthread.Execute;
begin
  // code to get the data goes here
  // for now simulate a 10 second delay
  sleep(10000);
  FValue := 666;
end;

function get_value: integer;
const
  OneSecond = 1000;
  DefaultValue = 999;
var
  LResult: dword;
  LWorker : TWorkthread;
begin
  // thread starts running immediately
  LWorker := TWorkthread.Create(False);    // TThread benötigt (False) bei D6
  try
    LResult := WaitForSingleObject(LWorker.Handle, OneSecond);
    if LResult = WAIT_OBJECT_0 then
      Result := LWorker.Value
    else if LResult = WAIT_TIMEOUT then begin
      LWorker.FreeOnTerminate := true;
      LWorker := nil;
      //abandon the thread
      Result := DefaultValue;
    end
    else
      raise Exception.CreateFmt('Thread creation failed, wait result was $%x',[LResult]);
  finally
    LWorker.Free;
  end;
end;

peterbelow 31. Jul 2019 13:35

AW: Default-Wert aus Funktion nach timeout (D6)
 
Zitat:

Zitat von HolgerX (Beitrag 1438464)
Hmm..


Zitat:

Zitat von peterbelow (Beitrag 1438451)
Versuchs mal hiermit.


kleine Korrectur für D6 ;)

Danke, solche Paläoversionen habe ich halt nicht mehr vorrätig :wink:


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