Конференция "Начинающим" » работа с потоками [D7]
 
  • aka © (09.11.17 14:31) [0]
    набросал минимальный примерчик, для пояснения сути вопроса

    Вот кусок примерный кода для пояснения вопроса:

    unit Main;

    interface

    uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     Dialogs, TrayIcon, Menus, ZAbstractConnection, ZConnection, StdCtrls,
     Buttons, ExtCtrls, IdBaseComponent, IdComponent, IdTCPConnection,
     IdTCPClient, IdTelnet, DB, ZAbstractRODataset, ZAbstractDataset, ZDataset, DateUtils;

    type
     TMainForm = class(TForm)
       procedure FormCreate(Sender: TObject);
       procedure TimerTimer(Sender: TObject);
     private
       { Private declarations }
       IPList: TStringList;
       ThreadArray: array of TThread;
       PredScanTime: TDateTime;    
     public
       { Public declarations }
     end;

     TTelnetThread = class(TThread)
     private
       IdTelnet: TIdTelnet;
       PortNo: Integer;
       IP: String;
       LastPortText: String;
       procedure ParsePortText;
       procedure DataAvailable(Sender: TIdTelnet; const Buffer: String);
     protected
       procedure Execute; override;
     public
       constructor Create(IP: String);
     end;

    var
     MainForm: TMainForm;

    implementation

    {$R *.dfm}

    procedure TMainForm.FormCreate(Sender: TObject);
    var
     i,j: Integer;
    begin
     IPList := TStringList.Create;
     IPList.LoadFromFile(ExtractFileDir(Application.ExeName)+'\IP.txt');
     PLList := TStringList.Create;

     PredScanTime := Now;
     SetLength(ThreadArray, IPList.Count);
    end;

    constructor TTelnetThread.Create(IP: String);
    begin
     inherited Create(True);
     IP := IP;
     LastPortText := '';
    end;

    procedure TTelnetThread.DataAvailable(Sender: TIdTelnet; const Buffer: String);
    begin
     LastPortText := LastPortText + Buffer;
    end;

    procedure TTelnetThread.ParsePortText;
    begin
      1) Парсим текст
      2) Вставляем в базу
    end;

    {Стартуем потоки каждые 5 минут}
    procedure TMainForm.TimerTimer(Sender: TObject);
    var
     i: Integer;
    begin
     if DateTimeToUnix(Now) > DateTimeToUnix(PredScanTime) + 300 {ScanInterval} then begin
        PredScanTime := Now;

        for i := 0 to Length(ThreadArray) - 1 do begin
          ThreadArray[i] := TTelnetThread.Create(IPList[i],PLList[i]);
          ThreadArray[i].FreeOnTerminate := True;
          ThreadArray[i].Priority := tpLower;
          ThreadArray[i].Resume;
        end;
     end;
    end;

    procedure TTelnetThread.Execute;
    var
     i: Integer;
    begin
     try
       IdTelnet := TIdTelnet.Create(nil);
       IdTelnet.OnDataAvailable := DataAvailable;
       IdTelnet.Host := IP;
       IdTelnet.Connect(-1);

       Sleep(2000);
       IdTelnet.Write('admin'+#13#10);
       Sleep(2000);
       IdTelnet.Write('admin'+#13#10);
     except

     end;

     try
       for i := 1 to 64 do begin
         LastPortText := '';
         PortNo := i;
         IdTelnet.Write('get port '+IntToStr(i)+' data'+#13#10);
         sleep(1500);

         Synchronize(ParsePortText);
       end;
     except

     end;

     IdTelnet.Free;
    end;

    end;

    end.



    Чем больше потоков, тем больше в БД пустых записей, до 30 потоков все 30X(64порта) =1960 записей на месте. Дальше чем больше потоков тем больше пустых в квадратичной прогрессии. В чем костыль?
  • Eraser © (10.11.17 00:35) [1]

    > aka ©   (09.11.17 14:31) 

    а что отладчик говорит по поводу работы с IdTelnet?
  • Игорь Шевченко © (10.11.17 12:01) [2]
    В древнем Китае людям, глушащим исключения, отрубали голову. Очень мудро поступали.
  • aka © (10.11.17 15:04) [3]

    > Игорь Шевченко ©   (10.11.17 12:01) [2]

    ))
    Да я просто постирал, чтобы топик был меньше и читаймей
  • aka © (10.11.17 15:15) [4]

    > Eraser ©   (10.11.17 00:35) [1]
    >
    >
    > > aka ©   (09.11.17 14:31)
    >
    > а что отладчик говорит по поводу работы с IdTelnet?


    Переменная LastPortText (которую и должны парсить) пустая. Но до конца пока не разобрался все равно в чем причина.

    Сделал сканирование в 3 очереди по 33,33,34 потока на 100 IP адресов. и все 64х100=6400 порта четко "ответили". Три дня идет сканирование каждые 30 мин и из 6400 * 48 *3 все ответило.

    Но стоит сделать чуть больше 40 потоков за раз и начинаются "дырки"
  • aka © (10.11.17 16:56) [5]

    > Игорь Шевченко ©   (10.11.17 12:01) [2]

    Игорь, ну что вам тяжело было сразу подсказать в чем вся загвоздка?

    вот на sql.ru сразу все объяснили))) :


    а ничего, что Microsoft настоятельно рекомендует не использовать в программе потоков количеством более, чем число ядер процессоров в системе * 2? У тебя банально операционка не дает квантов времени на выполнение потокам


    Прокомментируйте.
  • Игорь Шевченко © (10.11.17 17:54) [6]
    aka ©   (10.11.17 16:56) [5]

    там дальше столько всего написали :)
  • aka © (10.11.17 19:09) [7]
    Нужно будет попробовать после выходных IdTelnet.ThreadedEvent = true
  • Eraser © (10.11.17 22:34) [8]

    > aka ©   (10.11.17 19:09) [7]

    так он не синхронный по умолчанию что-ли? странно для индивых компонентов.
    конечно надо ставить, чтобы все было в отдельном потоке. желательно последовательно и синхронно. результат работы потока лучше всего получать через OnTerminate, которое выполняется в контексте основного потока, т.к. не нужно явно вызывать Synchronize.
  • aka © (10.11.17 23:52) [9]

    > так он не синхронный по умолчанию что-ли?

    Ну получается что DataAvailable в основном потоке

    procedure TTelnetThread.DataAvailable(Sender: TIdTelnet; const Buffer: String);
    begin
    LastPortText := LastPortText + Buffer;
    end;



    А я думал "что все как положено"
  • Eraser © (11.11.17 03:22) [10]
    property ThreadedEvent: Boolean;

    ThreadedEvent is a Boolean property that indicates if data handling and protocol suboption negotiations are executed in the context of the TelnetThread or synchronized to the main VCL thread for the application. Data handling and protocol negotiations are performed using the OnDataAvailable and the OnTelnetCommand event handlers.

    When ThreadedEvent contains True, event handlers notifications are executed in the context of the TelnetThread.

    When ThreadedEvent contains False, event handler notifications are synchronized to the main VCL thread. Set ThreadedEvent to False when the event handlers are not thread-safe or require access to classes and routines available only in the main VCL thread.

    The default value for ThreadedEvent is False.
  • aka © (11.11.17 11:12) [11]

    > Eraser ©   (11.11.17 03:22) [10]

    Нужно было это прочитать чуть раньше.
  • aka © (11.11.17 11:13) [12]
    Удалено модератором
 
Конференция "Начинающим" » работа с потоками [D7]
Есть новые Нет новых   [118460   +13][b:0][p:0.003]