Einzelnen Beitrag anzeigen

Benutzerbild von Jonas Shinaniganz
Jonas Shinaniganz

Registriert seit: 30. Aug 2011
249 Beiträge
 
Delphi XE5 Ultimate
 
#1

TThread Syncronise & TCriticalSection.Enter

  Alt 14. Mai 2014, 17:10
Hallo Forum, aus Interesse habe ich in aller Schnelle folgende App erstellt:

Es wird in einem IP-Bereich für jede Adresse eine NSLOOKUP Anfrage gestellt.

Delphi-Quellcode:
unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.Variants, System.UITypes,
  System.Classes, FMX.Types, FMX.Graphics, FMX.Dialogs, FMX.Types3D, FMX.Forms,
  FMX.Forms3D, FMX.Controls3D, IdGlobal, IdStack, FMX.Layers3D, FMX.StdCtrls,
  FMX.Controls, FMX.Layouts, FMX.Memo, SyncObjs;

type
  TForm1 = class(TForm3D)

    Memo: TMemo;
    ProgressBar: TProgressBar;
    Layer3D1: TLayer3D;
    AniIndicator1: TAniIndicator;
    procedure Form3DCreate(Sender: TObject);
  private
    Fprogress: Integer;
    procedure Setprogress(const Value: Integer);
  public
    Lock : TCriticalSection;
    property progress : Integer read Fprogress write Setprogress;
  end;

  MyThread = class(TThread)

  protected
    Ip : Integer;
    procedure Execute; override;
    procedure UnserThread;
  public
    constructor Create(next : Integer);

  end;

var
  Form1: TForm1;
  thrd : MyThread;
  stack : TIdStack;

const
  NET : String = '172.17.4.';

implementation

{$R *.fmx}

procedure MyThread.UnserThread;
var
  str : String;
begin
  TIdStack.IncUsage;
  try
    str := Gstack.HostByAddress(NET + IntToStr(Ip));
  except on E: Exception do
    str := 'inexistent domain';
  end;
  TIdStack.DecUsage;

  Synchronize(
  procedure
  var
    I : Integer;
  begin
    I := 0;
    Form1.Lock.Enter;

      if Form1.Memo.Lines.Count <= 0 then
        Form1.Memo.Lines.Insert(0, '...' + Format('%3d',[Ip])+ ' - ' + str)
      else
      begin
        while ((Form1.Memo.Lines[I]) < ('...' + Format('%3d',[Ip])+ ' - ' + str)) or (I <= Form1.Memo.Lines.Count) do
          inc(I);
        Form1.Memo.Lines.Insert(I, '...' + Format('%3d',[Ip])+ ' - ' + str);
      end;

    Form1.Lock.Leave;

    Form1.ProgressBar.Value := Form1.ProgressBar.Value + 1;
    Form1.progress := Form1.Progress + 1;
  end);

end;

procedure TForm1.Form3DCreate(Sender: TObject);
var
  i : integer;
begin
  Lock := TCriticalSection.Create;

  for I := 1 to 254 do
    thrd := MyThread.Create(I);

  ProgressBar.Min := 1;
  ProgressBar.Max := 254;
  ProgressBar.Value := 1;
  progress := 1;

  //Memo.Lines.Add('Parse Net: ' + NET + '...');
end;

{ MyThread }

constructor MyThread.Create(next : Integer);
begin
  inherited Create;
  Ip := next;
end;

procedure MyThread.Execute;
begin
  inherited;
  UnserThread;
end;

procedure TForm1.Setprogress(const Value: Integer);
begin
  Fprogress := Value;
  if Fprogress = 254 then
    AniIndicator1.Enabled := False;
end;

end.
Sobald der erste Thread in der Zeile Form1.Lock.Enter; ankommt, wird ja für alle Anderen Threads der Zugriff/Weiterverarbeitung blockiert die an dieser Stelle ankommen, bis der schnellste/erste Thread mit der Ausführung bei Form1.Lock.Leave; ankommt. Synchronize brauche ich zusätzlich, um Änderungen an der Oberfläche/Hauptthread machen zu können.

Ich habe wohl einen Denkfehler/Missverständnis. Es ist das Erste mal, dass ich mit diesen beiden Klassen Arbeite.
Beim Debuggen jedenfalls läuft es garnicht wie ich mir das vorstelle. Er springt wild hin und her, was ja bei 200+ Threads nicht ganz unverständlich ist.
Ich denke trotzdem das jemand mit Erfahrung bestimmt einen guten Tipp hat. Zur Abwechslung mache ich es mir also mal leicht und frage gleich!

Grüße!
Die Leiter der Entwicklungsabteilung dreht total am Mausrad!
  Mit Zitat antworten Zitat