Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi Thread Aufrufzeit vom Windows Sheduler (https://www.delphipraxis.net/190891-thread-aufrufzeit-vom-windows-sheduler.html)

AJ_Oldendorf 16. Nov 2016 21:19

Thread Aufrufzeit vom Windows Sheduler
 
Hallo zusammen,
ich habe 2 relativ schnelle Notebooks (CPU, RAM, SSD usw.), beide Windows 10 (inkl. Anniversary Update).
Hardware unterschiedlich. Kann wenn nötig, näher spezifiziert werden.

Folgender Code verhält sich unter beiden Rechnern unterschiedlich:

Delphi-Quellcode:
unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls, Vcl.StdCtrls;

const
  ttmSecond : Double = 1/(24*60*60*1000);

type
  TCycleThread = class(TThread)
  protected
    procedure Execute; override;
  private
    StartZyklus : TDateTime;

    Procedure Zyklus;
  public
    SollZykluszeit : Integer;
    IstZyklusZeit : Double;

    MinCycle,
    AktCycle,
    MaxCycle: Double;

    ChgEvent: TNotifyEvent;

    Constructor Create (CreateSuspended : Boolean);
    Destructor Destroy; override;
  end;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Label2: TLabel;
    Timer1: TTimer;
    Label3: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    { Private-Deklarationen }
    MyThread : TCycleThread;

    procedure ChangeEvent(Sender: TObject);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function Elapsedms(LastTime: TDateTime): Double;
begin
  Result := (Now - LastTime) / ttmSecond;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  H : THandle;
begin
  H := GetCurrentProcess();
  SetPriorityClass(H, HIGH_PRIORITY_CLASS);

  MyThread := TCycleThread.Create(True);
  MyThread.SollZykluszeit := 6;
  MyThread.ChgEvent := ChangeEvent;
  MyThread.Start;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if Assigned(MyThread) then
    FreeAndNil(MyThread);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Timer1.Enabled := False;
  if Assigned(MyThread) then
  begin
    Label2.Caption := 'kürzeste Zykluszeit: ' + MyThread.MinCycle.ToString;
    Label1.Caption := 'Aktuelle Zykluszeit: ' + MyThread.AktCycle.ToString;
    Label3.Caption := 'längste Zykluszeit: ' + MyThread.MaxCycle.ToString;
  end;
end;

procedure TForm1.ChangeEvent(Sender: TObject);
begin
  Timer1.Enabled := True;
end;

{ TCycleThread }

constructor TCycleThread.Create(CreateSuspended: Boolean);
begin
  Inherited Create (CreateSuspended);

  Priority := tpHighest;

  MinCycle := -1;
  AktCycle := -1;
  MaxCycle := -1;
end;

destructor TCycleThread.Destroy;
begin

  Inherited Destroy;
end;

procedure TCycleThread.Execute;
var
  Return        : LongWord;
  ThreadHandle  : THandle;
begin
  FreeOnTerminate := False;

  StartZyklus := Now;
  try
    while not Terminated do
    begin
      ThreadHandle := Self.ThreadID;
      Return := MsgWaitForMultipleObjects (0, ThreadHandle, False, SollZykluszeit, QS_ALLINPUT);
      if Return = WAIT_OBJECT_0 then
      begin

      end
      else
      begin
        if not Terminated then
        begin
          Zyklus;
        end;
      end;
    end;                                      
  finally
  end;
end;

procedure TCycleThread.Zyklus;
begin
  if Terminated then Exit;

  //Tue irgendwas
  IstZyklusZeit := (Elapsedms (StartZyklus));
  StartZyklus := Now;

  if (IstZyklusZeit < MinCycle) or (MinCycle = -1) then
    MinCycle := IstZyklusZeit;

  AktCycle := IstZyklusZeit;

  if (IstZyklusZeit > MaxCycle) or (MaxCycle = -1) then
    MaxCycle := IstZyklusZeit;

  if Assigned(ChgEvent) then
    ChgEvent(Self);
end;

end.
Auf Rechner A wird die Sollzykluszeit von 6ms eingehalten (AktCycle), auf Rechner B wird immer 16ms angezeigt.
Das liegt ja sicherlich am Windows Sheduler oder sehe ich das falsch? Die Frage ist, kann man am Rechner noch irgendwas einstellen, dass Rechner B ein gleiches Zeitverhalten hat wie Rechner A?

Ich hoffe ihr könnt mir da weiterhelfen.

jaenicke 16. Nov 2016 22:36

AW: Thread Aufrufzeit vom Windows Sheduler
 
Du könntest es einmal mit timeBeginPeriod versuchen.

himitsu 16. Nov 2016 23:57

AW: Thread Aufrufzeit vom Windows Sheduler
 
Und was machst du, wenn das Notebooks der Rechner in einen Energiesparmodus schaltet,
oder wenn gerade die Festplatte ausgelastet ist und das System etwas hängt
oder wenn grade ein anderes Programm viel Rechenleistung braucht
oder ... ?

Windows ist nunmal (standardmäßig) kein Echtzeitsystem und man kann einfach niemals für so kleine Zeiteinheiten eine zuverlässige und überall einheitliche Ausführung garantieren.
Selbst unter idealen Bedingungen (keine Systemauslastung), muß man mit Abweichungen von bis zu (meistens) 16 bzw. ~20 Millisekunden rechnen.

Abgesehn davon, dass Windows jederzeit am Scheduler was ändern.
* andere Windows-Version oder Edition (Server- oder UserSystem)
* aufgrund unterschiedlicher Hardware (CPU usw.)
* unterschiedliche Powerstates
* ...

AJ_Oldendorf 17. Nov 2016 06:38

AW: Thread Aufrufzeit vom Windows Sheduler
 
Hallo,

@jaenicke: Ich werde mir mal timeBeginPeriod angucken, danke.

@himitsu:
Ich weiß das Windows kein Echtzeitsystem ist. Auf beiden Rechnern läuft kein Energiesparmodus, Festplatten können sich nicht ausschalten, keine anderen Programme laufen (außer natürlich die ganzen Windows Dienste), Cortana und die ganzen Hintergrund Apps sind alle deaktiviert. Daher wollte ich wissen, ob man an dem Windows Sheduler selber etwas machen könnte (konfigurieren) um mehr Rechenleistung in das eine Programm geben zu können.
Der eine Rechner schafft sogar 1ms, wenn ich das einstelle nur merkt man dann natürlich, dass die VCL ziemlich hängt. Das will ich auch gar nicht, mit der 1ms, ich würde nur eben gerne das Verhalten gleich haben. Liegt das jetzt an irgendwelchen Windows Einstellungen oder doch an der Hardware?

Zacherl 17. Nov 2016 07:13

AW: Thread Aufrufzeit vom Windows Sheduler
 
Zitat:

Zitat von AJ_Oldendorf (Beitrag 1353923)
Das will ich auch gar nicht, mit der 1ms, ich würde nur eben gerne das Verhalten gleich haben. Liegt das jetzt an irgendwelchen Windows Einstellungen oder doch an der Hardware?

Kurz und schmerzlos: Vergiss es. Es liegt sowohl an der Hardware, als auch an Windows selbst. Es kann jederzeit ein Interrupt deinen Thread unterbrechen. Außerdem kann die Hardware jederzeit zufällig ein System Management Interrupt auslösen, welcher das komplette System für einige Milisekunden unterbricht. Hierbei bekommt nichtmal Windows selbst mit, dass es unterbrochen wurde.

Sind solche minimalen Differenzen denn überhaupt in irgeindeiner Form für den Nutzer zu erkennen?

AJ_Oldendorf 17. Nov 2016 07:20

AW: Thread Aufrufzeit vom Windows Sheduler
 
Der Hintergrund ist, das über eine extra Steckkarte im PC, Werte in dieser Karte < 1ms aktualsiert.
Deswegen möchte ich so schnell wie möglich, diese Werte auslesen und speichern können.

Schade, dass man an der Zeitscheibe nicht selber bisschen drehen kann. Aber danke für die Infos.

Uwe Raabe 17. Nov 2016 07:37

AW: Thread Aufrufzeit vom Windows Sheduler
 
Zitat:

Zitat von AJ_Oldendorf (Beitrag 1353930)
Der Hintergrund ist, das über eine extra Steckkarte im PC, Werte in dieser Karte < 1ms aktualsiert.
Deswegen möchte ich so schnell wie möglich, diese Werte auslesen und speichern können.

Da kann dir verlässlich nur ein Echtzeitsystem helfen - z.B. Kithara.

Der schöne Günther 17. Nov 2016 07:56

AW: Thread Aufrufzeit vom Windows Sheduler
 
Und diese Karte ist nicht fähig, selbst ein bisschen zu puffern?

Zacherl 17. Nov 2016 08:02

AW: Thread Aufrufzeit vom Windows Sheduler
 
Wenn es nicht wirklich um Echtzeit geht, sondern nur um "so schnell wie möglich", dann lass den Thread doch einfach auf Volllast laufen, komplett ohne zu warten. Dann ist halt ab und zu mal kein neuer Datensatz vorhanden und in anderen Fällen evtl. schon Mehrere (falls die Karte buffert).
Auf der anderen Seite ist es doch bei so frequenten Messdaten meistens nicht wirklich erforderlich (bzw. gewünscht) wirklich jeden Datensatz zu erfassen, da man oft ja eh nur irgendeine Form von Mittelwert bilden will.

AJ_Oldendorf 17. Nov 2016 08:26

AW: Thread Aufrufzeit vom Windows Sheduler
 
Ja ich will alle Daten haben zum späteren auswerten.
Volllast den Thread laufen lassen kann ich nicht, da das eigentliche Programm noch mehr Threads hat und auch eine Visu. Das soll ja alles weiterhin laufen.


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