![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как избежать гонок в потоках [D6, WinXP]
leonidus © (2005-05-31 10:38:00)Мастера подскажите пожалуйста. Я написал небольшую программу, она скачивает новости с разных сайтов, и затем парсит каждую скачанную страницу на предмет нужной информации. Т.е. программа состоит из бвух блоков - блок закачки (качается сразу в несколько потоков, для каждой страницы с новостями свой поток) и блок парсинга (в нем также предусмотрена многопоточность, при этом для каждой скачанной страницы должен запускаться свой экземпляр одного и тогоже потока). Результаты парсинга (заголовки новостей) помещаются в массив. И вот в чем проблема. Если одновременно скачаются две страницы и одновременно начнут работать два парсера, то может так получиться, что они будут обращаться к одному элементу массив, что бы записать в него полученный заголовок новости. Т.е. я тап понимаю это ситуация гонок. Подскажите как этого избежать. Может есть какие-то статьи по этому поводу, я что-то ничего толком не нашел. Заранее спасибо.
Семен Сорокин (2005-05-31 15:26:00) [81]
> где грабли?
а вот про это:
synchronize(showresult);
в Execute не забыли?
leonidus (2005-05-31 15:07:00) [82]Понятно...в общем делаю так:
type
...
...
TThread_work = class(TThread)
private
{ Private declarations }
st:string;
protected
procedure Execute; override;
procedure showresult;
public
end;
var
FCS:TCriticalSection;
t:TThread_work;
a:array[1..10] of string;
nom:integer;
implementation
{$R *.dfm}
procedure TThread_work.showresult;
var
i:integer;
begin
for i:=1 to nom do
begin
form1.memo1.Lines.Add(a[i]);
end;
form1.memo1.Lines.Add('---');
end;
procedure TThread_work.Execute;
begin
FCS.Enter;
inc(nom);
a[nom]:=t.st;
FCS.Leave;
synchronize(showresult);
end;
procedure TForm1.Button1Click(Sender: TObject);
//запускаем потоки
begin
FCS:=TCriticalSection.Create;
nom:=0;
t:=TThread_work.Create(true);
t.FreeOnTerminate:=true;
t.st:='поток1';
t.Resume;
t:=TThread_work.Create(true);
t.FreeOnTerminate:=true;
t.st:='поток2';
t.Resume;
end;
в результате получаются не однозначная картина то
поток1
поток2
---
то вообще:
поток1
---
где грабли?
Игорь Шевченко (2005-05-31 11:27:00) [83]leonidus © (31.05.05 11:08) [2]
> а еще примеры по проще есть
Есть. Например, TThreadList в classes.pas
Anatoly Podgoretsky (2005-05-31 11:22:00) [84]Может вместо критических секци даже лучше использовать специализирование средство TMultiReadExclusiveWriteSynchronizer
Digitman (2005-05-31 11:14:00) [85]
> может так получиться, что они будут обращаться к одному
> элементу массив
синхронизация тебе нужна .. смотри все касаемое критических секций
leonidus (2005-05-31 11:08:00) [86]Спасибо Игорь, а еще примеры по проще есть, а то там клиент-сервер и мне сложновато зерна от плевел отделить?
Игорь Шевченко (2005-05-31 10:56:00) [87]Использовать синхронизацию, например, защищать обращения к массиву критической секцией. Примеры есть в Program Files/Borland/Delphi/Demos/Midas/Pooler/*.*