Мастера DELPHI, Delphi programming community Рейтинг@Mail.ru Титульная страница Поиск, карта сайта Написать письмо 
| Новости |
Новости сайта
Поиск |
Поиск по лучшим сайтам о Delphi
FAQ |
Огромная база часто задаваемых вопросов и, конечно же, ответы к ним ;)
Статьи |
Подборка статей на самые разные темы. Все о DELPHI
Книги |
Новинки книжного рынка
Новости VCL
Обзор свежих компонент со всего мира, по-русски!
|
| Форумы
Здесь вы можете задать свой вопрос и наверняка получите ответ
| ЧАТ |
Место для общения :)
Орешник
Коллекция курьезных вопросов из форумов
Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / rsdn.org

 
Чтобы не потерять эту дискуссию, сделайте закладку « предыдущая ветвь | форум | следующая ветвь »

работа с потоками [D7]


aka ©   (09.11.17 14:31

набросал минимальный примерчик, для пояснения сути вопроса

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

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]

Удалено модератором


версия для печати

Написать ответ

Ваше имя (регистрация  E-mail 







Разрешается использование тегов форматирования текста:
<b>жирный</b> <i>наклонный</i> <u>подчеркнутый</u>,
а для выделения текста программ, используйте <code> ... </code>
и не забывайте закрывать теги! </b></i></u></code> :)


Наверх

  Рейтинг@Mail.ru     Титульная страница Поиск, карта сайта Написать письмо