Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > Интернет и сети
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Ответ
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 31.01.2012, 23:20
syserg syserg вне форума
Прохожий
 
Регистрация: 26.01.2009
Сообщения: 15
Репутация: 10
По умолчанию Многопоточность с ограниченным количеством потоков

Уважаемые программисты, направьте на путь.
Есть список URL в TStringList. Я забираю данные с этих страниц к себе в базу.
Многопоточность создать удалось, но куча косяков.
Среди них не могу по-челевечески решить следующий вопрос:

Я хочу устанавливать количество одновременно работающих потоков, например 8, а записей пусть 100.
Как мне это верно организовать?

Т.е. мне нужно отслеживать количество работающих потоков, как только какие-то освободились, подгружать новые?

Код:
    unit unit1;
     
    procedure TF_Irr.GetCache(SL:TStringList; threads:integer);
    var i,j,thrds,len:integer;
    a: array of TMyThread1;
    begin
    alive:=0; //живые потоки
    i:=0;
    thrds:=threads; //количество мной установленных потоков
    len:=SL.Count;
     
    //А ДАЛЬШЕ - МОЯ ФАНТАЗИЯ, КОТОРАЯ, Я УВЕРЕН, ДОЛЖНА ПРОЩЕ РЕШАТЬСЯ
     
    SetLength(a,len);
    repeat
    if i<=len-1 then begin
     
    if (len-i)<thrds  then begin thrds:=len-i; alive:=0; end;
    if alive<thrds then begin
    for j:=i to (thrds-alive-1+i) do begin
    a[j]:=TMyThread1.Create(true,SL[i]);
    a[j].Resume; //запускаем процедуру загрузки данных
    inc(i);
     
    end;
    end else a[i-1].WaitFor;
    end;
     
    until i>len-1;
     
     
    end;
     
     
    ///////////////////////////////////////
    unit thread;
     
    constructor TMyThread1.Create(CreateSuspended: boolean; AURL: string);
    begin
    inherited Create(CreateSuspended);
    FURL:=AURL;
     
    InterlockedIncrement(alive);
    Priority:=tpHigher;
    //FreeOnTerminate:=true;
    OnTerminate:=ThreadExit;
    //Resume;
    end;
     
     
    procedure TMyThread1.ThreadExit(Sender: TObject);
    begin
    InterlockedDecrement(alive);
    synchronize(ShowAlive);
    end;
     
    procedure TMyThread1.Execute;
    var
    s,ch: string;
    i: integer;
    inStream: TMemoryStream;
    E: Exception;
    idHTTP: TIdHTTP;
    idCompress:TIdCompressorZLib;
    begin
    //код процедуры
    synchronize(ShowResult);
    Terminate;
    end;
     
    procedure TMyThread1.ShowResult;
    begin
    //куда-нить записываю данные, пусть в memo
    end;

На одном из форумов получил ответ:
Цитата:
Незачем постоянно создавать-уничтожать потоки, можно просто организовать синхронизированное извлечение следующего URL из списка. Тогда потоков создашь столько, сколько нужно, в начале цикла, а по получении всех адресов они тихо завершатся

Подскажите наиболее верное решение. Я только начал знакомиться с потоками.

Заранее огромное спасибо
Ответить с цитированием
  #2  
Старый 01.02.2012, 03:53
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,020
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Тебе в сторону CriticalSection.
Собственно, тебе надо сделать следующую вещь (как бы делал я):
1. Делаем объект-одиночку для списка адресов.
2. Делаем объект пула потоков. Можно помотреть, по-моему в Indy уже такой есть. Его задача контролировать сам список потоков.
3. Делаем класс потоков. В своем состоянии ничего не делания он должен каждые по-секунды, например, просыаться и спрашивать у объекта одиночки - есть ли задания для него. Если нет - то засыпаем опять. Получения задания нужно сделать через CriticalSection, что не даст нескольким потокам вытащить один и тот же адрес. В этом месте они просто встанут в очередь.
4. Потоки можно создать сразу и уничтожить при закрытии программы.

Это простой вариант. Есть еще сложный, когда потоки будут извещать о том, что им делать нечего и умирать, а какой-нить менеджер будет из создавать и раздавать задания. Вопрос - нужно ли это.
Ответить с цитированием
  #3  
Старый 01.02.2012, 09:59
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Цитата:
Сообщение от syserg
Я хочу устанавливать количество одновременно работающих потоков, например 8, а записей пусть 100.
Как мне это верно организовать?
используй семафоры Semaphore Objects (добавить всего 4 функции):
Код:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TTestThread = class(TThread)
  private
    FNum: Integer;
    procedure SynchAdd();
    procedure SynchDel();
  protected
    procedure Execute; override;
  public
    constructor Create(ANum: Integer);
  end;

  TForm1 = class(TForm)
    Button1: TButton;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

const
  InitialCount = 8;

var
  Form1: TForm1;
  hSemaphore: THandle;

implementation

{$R *.dfm}

{ TTestThread }

constructor TTestThread.Create(ANum: Integer);
begin
  inherited Create(True);
  FreeOnTerminate:=True;
  FNum:=ANum;
  Resume;
end;

procedure TTestThread.Execute;
begin
  WaitForSingleObject(hSemaphore, INFINITE);
  Synchronize(SynchAdd);
  Sleep(100+Random(100));
  Synchronize(SynchDel);
  ReleaseSemaphore(hSemaphore, 1, nil);
end;

procedure TTestThread.SynchAdd;
begin
  Form1.Tag:=Form1.Tag+1;
  Form1.Label1.Caption:=IntToStr(Form1.Tag);
end;

procedure TTestThread.SynchDel;
begin
  Form1.Tag:=Form1.Tag-1;
  Form1.Label1.Caption:=IntToStr(Form1.Tag);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  for i:=1 to 100 do TTestThread.Create(i);
end;

initialization
  hSemaphore:=CreateSemaphore(nil, InitialCount, InitialCount, nil);

finalization
  CloseHandle(hSemaphore);

end.
основной код потока должен выполняться между WaitForSingleObject и ReleaseSemaphore. WaitForSingleObject будет ждать сигнала разрешения от семафора для которого установлено MaximumCount = 8.
http://data.cod.ru/141194
__________________
Пишу программы за еду.
__________________

Последний раз редактировалось NumLock, 01.02.2012 в 10:02.
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
bulldog (30.11.2012)
  #4  
Старый 01.02.2012, 13:05
syserg syserg вне форума
Прохожий
 
Регистрация: 26.01.2009
Сообщения: 15
Репутация: 10
По умолчанию

Спасибо. Буду пробовать/кумекать
Ответить с цитированием
  #5  
Старый 03.02.2012, 23:13
syserg syserg вне форума
Прохожий
 
Регистрация: 26.01.2009
Сообщения: 15
Репутация: 10
По умолчанию

NumLock: MaximumCount = 8 - константа. Пожскажи, а просто, как переменную я разве не могу задать?
Ответить с цитированием
  #6  
Старый 03.02.2012, 23:19
Аватар для angvelem
angvelem angvelem вне форума
.
 
Регистрация: 18.05.2011
Адрес: Омск
Сообщения: 3,970
Версия Delphi: 3,5,7,10,12,XE2
Репутация: выкл
По умолчанию

Можешь,
Код:
var
  MaximumCount : Integer = 8;
__________________
Je venus de nulle part
55.026263 с.ш., 73.397636 в.д.
Ответить с цитированием
  #7  
Старый 04.02.2012, 08:52
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Код:
hSemaphore:=CreateSemaphore(nil, 8, 8, nil);
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
bulldog (30.11.2012)
  #8  
Старый 16.02.2012, 16:55
name_00 name_00 вне форума
Прохожий
 
Регистрация: 16.02.2012
Сообщения: 1
Репутация: 10
По умолчанию

NumLock, а можете подсказать, что делать если записей ооочень много? столько потоков одновременно наметво вешают систему
Ответить с цитированием
  #9  
Старый 16.02.2012, 17:09
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

пересмотреть алгоритм!
__________________
Пишу программы за еду.
__________________
Ответить с цитированием
Этот пользователь сказал Спасибо NumLock за это полезное сообщение:
bulldog (30.11.2012)
Ответ


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 01:19.


 

Сайт

Форум

FAQ

RSS лента

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2023

ВКонтакте   Facebook   Twitter