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

Delphi Sources



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

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

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

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

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

Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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,096
Версия 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 функции):
Код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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
  <font color="red">WaitForSingleObject(hSemaphore, INFINITE);</font>
  Synchronize(SynchAdd);
  Sleep(100+Random(100));
  Synchronize(SynchDel);
  <font color="red">ReleaseSemaphore(hSemaphore, 1, nil);</font>
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;
 
<font color="Red">initialization
  hSemaphore:=CreateSemaphore(nil, InitialCount, InitialCount, nil);
 
finalization
  CloseHandle(hSemaphore);</font>
 
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
Репутация: выкл
По умолчанию

Можешь,
Код:
1
2
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
По умолчанию

Код:
1
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:36.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

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