![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
|
|
#1
|
|||
|
|||
|
Уважаемые программисты, направьте на путь.
Есть список 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;На одном из форумов получил ответ: Цитата:
Подскажите наиболее верное решение. Я только начал знакомиться с потоками. Заранее огромное спасибо |
|
#2
|
|||
|
|||
|
Тебе в сторону CriticalSection.
Собственно, тебе надо сделать следующую вещь (как бы делал я): 1. Делаем объект-одиночку для списка адресов. 2. Делаем объект пула потоков. Можно помотреть, по-моему в Indy уже такой есть. Его задача контролировать сам список потоков. 3. Делаем класс потоков. В своем состоянии ничего не делания он должен каждые по-секунды, например, просыаться и спрашивать у объекта одиночки - есть ли задания для него. Если нет - то засыпаем опять. Получения задания нужно сделать через CriticalSection, что не даст нескольким потокам вытащить один и тот же адрес. В этом месте они просто встанут в очередь. 4. Потоки можно создать сразу и уничтожить при закрытии программы. Это простой вариант. Есть еще сложный, когда потоки будут извещать о том, что им делать нечего и умирать, а какой-нить менеджер будет из создавать и раздавать задания. Вопрос - нужно ли это. |
|
#3
|
||||
|
||||
|
Цитата:
Код:
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.http://data.cod.ru/141194 Последний раз редактировалось NumLock, 01.02.2012 в 10:02. |
| Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
bulldog (30.11.2012)
| ||
|
#4
|
|||
|
|||
|
Спасибо. Буду пробовать/кумекать
![]() |
|
#5
|
|||
|
|||
|
NumLock: MaximumCount = 8 - константа. Пожскажи, а просто, как переменную я разве не могу задать?
|
|
#6
|
||||
|
||||
|
Можешь,
Код:
var MaximumCount : Integer = 8; |
|
#7
|
||||
|
||||
|
Код:
hSemaphore:=CreateSemaphore(nil, 8, 8, nil); |
| Этот пользователь сказал Спасибо NumLock за это полезное сообщение: | ||
bulldog (30.11.2012)
| ||