Einzelnen Beitrag anzeigen

Kas Ob.

Registriert seit: 3. Sep 2023
431 Beiträge
 
#45

AW: Thread.Queue, Zeitmessung, Thread hängt angeblich

  Alt 21. Mai 2025, 15:13
IdUDPClient liegt auf einem Datenmodul welches mit .Create(Nil); erzeugt wird.
Also nein, es hat keinen Owner.

Das Senden mit IdUDPClient sieht so aus:
Delphi-Quellcode:
IdUDPClient.SendBuffer(MyDModul.IdUDPClient.Host,
                       MyDModul.IdUDPClient.Port,
                       ByteMsg);
Eine Prüfung genau an dieser Stelle auf "MainThreadID" und "GetCurrentThreadID" sagt auch, KEIN VCL Kontext.

Das Thema mit den 250ms ist in dem Verarbeitungsthread, hat nichts mit dem Client-Thread zu tun! Das Thema sollten wir nicht weiter betrachten.

Richtig, dass Hauptproblem ist nach wie vor die hängende VCL für ~ 7s.
Interessant ist, es sind wirklich immer ~ 7s, bei jedem Test.

Gibt es eine Möglichkeit, dass ich selber herausbekomme, was der VCL Kontext/Thread gerade gemacht? Ich glaube nämlich nicht, dass das UDP Thema damit eine Rolle spielt. Ich kann es nur dadurch erzeugen, da ich damit so viele Threads gleichzeitig beende.
Saying killing so many threads at once can cause this, make my sad.
Here a simple test that will create 50000 threads and exits them, no killing just exit gracefully, creating them in fraction of second and exit them in second(s):
Delphi-Quellcode:
unit Unit10;

interface

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

type
  TForm10 = class(TForm)
    Timer1: TTimer;
    Label1: TLabel;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
  private
    procedure CreateOneThread;
    procedure CreateThreads(Count: Integer);
  public
    { Public declarations }
  end;

var
  Form10: TForm10;

implementation

{$R *.dfm}

var
  CurrentThreadCount: Integer;

const
  CREATE_MANY_THREADS = 50000;
  THREADS_STACK_SIZE = 64 * 1024;
  STACK_SIZE_PARAM_IS_A_RESERVATION = $00010000;

function ThreadFunc(Parameter: Pointer): Integer;
begin
  InterlockedIncrement(CurrentThreadCount);
  Sleep(4000);
  InterlockedDecrement(CurrentThreadCount);
  EndThread(0);
end;

procedure TForm10.FormCreate(Sender: TObject);
begin
  Timer1.Interval := 50;
end;

procedure TForm10.CreateOneThread;
var
  ThreadId: Cardinal;
  ThreadHandle: THandle;
begin
  ThreadHandle := BeginThread(nil, THREADS_STACK_SIZE, Addr(ThreadFunc), 0, STACK_SIZE_PARAM_IS_A_RESERVATION, ThreadId);
  if ThreadHandle <> 0 then
    CloseHandle(ThreadHandle);
end;

procedure TForm10.CreateThreads(Count: Integer);
begin
  while Count > 0 do
  begin
    CreateOneThread;
    Dec(Count);
  end;
end;

procedure TForm10.Button1Click(Sender: TObject);
begin
  if IsDebuggerPresent then
    CreateThreads(10)
  else
    CreateThreads(CREATE_MANY_THREADS);
end;

procedure TForm10.Timer1Timer(Sender: TObject);
begin
  Label1.Caption := IntToStr(CurrentThreadCount);
end;

end.
Build it for 64bit not 32bit, and don't run it in the debugger as it will kill the IDE, try to increase the created and exited threads to 100k, will there be a big difference.

Anyway all Indy components are tied internally to singletons that track their creation and lifetime, using CciticalSection and try to look for singleton that protect from hanging and freezing also for logging...etc..
I am not expert on Indy but you approach even with 35 connection is wrong and cause this.

Away from that there is no solution like put this line and it will work fine.

ps: when running that test of 50k threads watch the red against the green in Process Explorer.
Kas
  Mit Zitat antworten Zitat