Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.190.217.134] |
|
Сообщ.
#1
,
|
|
|
набросал минимальный примерчик, для пояснения сути вопроса
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'); 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]); 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. Чем больше потоков, тем больше LastPortText = '', до 30 потоков все 30X(64порта) =1960 записей на месте. Дальше чем больше потоков тем больше пустых LastPortText в квадратичной прогрессии. В чем костыль? Как количесво потоков можем повлиять на то, что idTelnet не успевает вернуть ответ, если он сам же в отдельном потое? так же быть не должно. Вобщем чем больше потоков тем больше я теряю данных, до 30 потоков не теряю ничего. Может проблема в самом idTelnet ? |
Сообщ.
#2
,
|
|
|
Цитата aka @ constructor TTelnetThread.Create(IP: String); ... IP := IP; Это опечатка при "наброске минимального примерчика"? Цитата aka @ Как количесво потоков можем повлиять на то, что idTelnet не успевает вернуть ответ, если он сам же в отдельном потое? так же быть не Если ты не устанавливаешь IdTelnet.ThreadedEvent = true, то метод IdTelnet.OnDataAvailable выполняется через Synchronize в основном потоке приложения. Это создает огромную очередь обращений потоков к основному потоку с соответствующими ожиданиями и тормозами (30 потоков по 64 с лишним вызова Synchronize в каждом - итого около 2000). При этом на каждый ответ ты отводишь только 1.5 сек, чего м.б. недостаточно при такой огромной очереди. |