Форум программистов, компьютерный форум, киберфорум
Delphi для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 5.00/26: Рейтинг темы: голосов - 26, средняя оценка - 5.00
1 / 1 / 2
Регистрация: 26.08.2013
Сообщений: 381

Правильно ли организован поток?

08.10.2014, 20:12. Показов 5749. Ответов 94
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем доброго времени суток, задался таким вопросом, а правильно ли составлен этот код потока, основан на критической секции. привожу :
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
procedure TPotok.Execute;
var memolines:tstringlist;
begin
 while Work do
  begin
   CS.Enter;
    Inc(cc); 
    if cc<Peremennya.Count-1 then Cur:=cc else Work:=false;
   CS.Leave;
   if Work then
    begin
// тут всякие действия, к примеру
memolines:=tstringlist.create;
memolines.add('Stroka = '+Peremennya[Cur]);
     Synchronize(Sync);
    end;
  end;
 dec(Thread);
end;
 
procedure TPotok.Sync;
begin
form1.memo1.lines.add(memo1.lines.text);
end;
Вызываю так :
Delphi
1
2
3
4
5
6
7
cc:=-1;
 Work:=true;
 for Thread:=0 to strtoint(sEdit1.TExt) do
 begin
  TPotok.Create(false);
 end;
  Thread:=strtoint(sEdit1.TExt);
Ибо иногда выполняет выводит одни и те же строки. Плохо работает с idhhtp , синапсом. Иногда просто не догружает страницу.(с прокси) да и без прокси иногда. Может я не правильно реализовал ?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
08.10.2014, 20:12
Ответы с готовыми решениями:

Правильно вызвать поток
Вызываю поток следующим образом repeat for Thread3:=0 to form3.sSpinEdit1.Value do begin with TStas.Create(true) do begin ...

Правильно ли организован поток в приведенном коде
Всё ли я правильно делаю? Почему в цикле на Table не ругается, а на ТекстБокс ругается? bool flag = false;; Thread _t =...

Правильно ли организован ввод строки
Всем добрый день! Подскажите, правильно ли я ввожу строку? //---------------------------------------------------------------------------...

94
16.10.2014, 02:29
Студворк — интернет-сервис помощи студентам

Не по теме:

Как слепому объяснить как выглядит радуга?
Как глухому объяснить как поёт соловей?

0
1 / 1 / 2
Регистрация: 26.08.2013
Сообщений: 381
05.11.2014, 22:21  [ТС]
простите за назойливость, а так будет ли верно организован поток :

Delphi
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
/// на кнопку старта
var
  t: TRecursiveSearchThread;
  i:integer;
begin
 
 
  ListView1.clear;
  processqueueform.listbox1.clear;
  for i := 0 to memo1.lines.count-1 do begin
 
  t := TRecursiveSearchThread.Create(true);
  with t do
  begin
    Priority := tpLower;
    stran := memo1.lines[i];
    FreeOnTerminate := true;
    OnTerminate := HandleThreadTerminate;
    FThreads.add(t);
    resume;
  end;
  end;
  ToggleButtons;
 
/// в самом потоке 
FStran: string;
property stran: string read Fstran write Fstran;
 
.....
 
procedure TRecursiveSearchThread.Execute;
var
 i: Integer;
    HTTP:THTTPSend;
    HTML, src:TStringList;
begin
  inherited;
 
 HTTP:=THTTPSend.Create;
     with HTTP do begin
           MimeType:='application/x-www-form-urlencoded';
      UserAgent:= 'Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1';
     end;
       HTTP.HTTPMethod('GET',PChar('http://yaca.yandex.ua/yca/cat/'+FStran+'.html?text=101&ncrnd=22&nocookiesupport=yes'));
       if pos('200', HTTP.Headers.Text)<>0 then  begin
       src:=Tstringlist.Create;
      sit2:=Tstringlist.Create;
     src.LoadFromStream(HTTP.Document);
   ParseStr(src.Text, '<h3 class="b-result__head"><a href="http://', '/', sit2);
 
       end;
Synchronize(Found);
end;
procedure TRecursiveSearchThread.Found;
begin
  ProcessQueueForm.Queue(sit2.Text);
end;

работает все хорошо, но правильно ли все организовал ? этот вариант по лучше варианта в 1 посте ? (имеется в виду организация потока) . Буду очень благодарен за все ваши отзывы
0
Модератор
 Аватар для FIL
3492 / 2614 / 742
Регистрация: 19.09.2012
Сообщений: 7,977
05.11.2014, 22:53
Уже лучше, но то, что делает Synchronize(Found) следует перенести в HandleThreadTerminate.
И нет освобождения создаваемых тобой компонентов.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
05.11.2014, 23:02
Лучше вообще методом Синхронайз не пользоваться, особенно если осн.поток непрерывно и интенсивно работает с гуёвыми событиями ввода-вывода.

В идеале при создании доп.потока ему в числе параметров передается еще и некий потокозащищенный объект-очередь Queue, в хвост которой доп.поток может по завершению вычислений поставить их результаты, а из головы которой другой заинтересованный поток (например, основной) выгребает эти результаты для дальнейшей обработки.

Ну и про освобождение объектов, создаваемых в контексте доп.потока, замечание вполне уместно.
+ обработка потенциальных исключений нужна.
0
пофигист широкого профиля
4770 / 3206 / 862
Регистрация: 15.07.2013
Сообщений: 18,613
06.11.2014, 01:46
Цитата Сообщение от mss Посмотреть сообщение
Лучше вообще методом Синхронайз не пользоваться
Как и классом TThread.
0
06.11.2014, 08:16

Не по теме:

Цитата Сообщение от northener Посмотреть сообщение
Как и классом TThread
"Эт точно"

0
1 / 1 / 2
Регистрация: 26.08.2013
Сообщений: 381
06.11.2014, 18:02  [ТС]
Цитата Сообщение от FIL Посмотреть сообщение
то, что делает Synchronize(Found) следует перенести в HandleThreadTerminate.
Сделал так :
Delphi
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
// переменная в потоке
flolka:string;
property lolka: string read Flolka write Flolka;
 
...
 
// в самом потоке
procedure TRecursiveSearchThread.Execute;
var
 i: Integer;
   f:Integer;
   CurAcc, TP:integer;
    HTTP:THTTPSend;
    IP, Port:string;
    data:TStringStream;
    HTML:TStringList;
begin
  inherited;
 // ProcessDirectory(IncludeTrailingPathDelimiter(StartDir));
 HTTP:=THTTPSend.Create;
     with HTTP do begin
           MimeType:='application/x-www-form-urlencoded';
      UserAgent:= 'Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1';
     end;
       HTTP.HTTPMethod('GET',PChar('http://yaca.yandex.ua/yca/cat/'+StartDir+'.html?text=101&ncrnd=22&nocookiesupport=yes'));
       if pos('200', HTTP.Headers.Text)<>0 then  begin
       src:=Tstringlist.Create;
      sit2:=Tstringlist.Create;
     src.LoadFromStream(HTTP.Document);
   ParseStr(src.Text, '<h3 class="b-result__head"><a href="http://', '/', sit2);
       flolka:=sit2.Text;
       end;
       http.Free;
       src.Free;
       sit2.Free;
       //Synchronize(FileFound);
end;
 
...
 
// в гл. форме
procedure TMainForm.HandleThreadTerminate(Sender: TObject);
var
  i: integer;
begin
 
  if sender is TWorkerThread then
    TWorkerThread(Sender).ProgressBar.Free;
 
  memo2.Lines.Add(TRecursiveSearchThread(Sender).lolka);
 
  for i := 0 to FThreads.count-1 do
    if sender = FThreads[i] then
    begin
 
      FThreads.Delete(i);
      break;
    end;
 
  ToggleButtons;
end;
правильно все сделал ? если нет, то пожалуйста, поправьте

а так же, не подскажите правильно ли реализовал присвоение кол-во потоков :

Delphi
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
 FMaxThreads := StrToInt(edit2.text);
  HandleFileQueued(self);
end;
 
procedure TMainForm.HandleFileQueued(Sender: TObject);
var
  t: TWorkerThread;
  p: TCustomProgressBar;
begin
  if FThreads.count > FMaxThreads then
    TThread(FThreads[FThreads.count-1]).Terminate;
 
  if (FThreads.Count < FMaxThreads)
    and (ProcessQueueForm.Count > 0) then
  begin
    t := TWorkerThread.create(true);
    with t do
    begin
      Priority := tpLowest;
      FreeOnTerminate := true;
      OnTerminate := HandleThreadTerminate;
      p := TCustomProgressBar.Create(nil);
      p.Parent := ScrollBox1;
      ProgressBar := p;
      FThreads.add(t);
      Resume;
    end;
  end;
end;

Цитата Сообщение от mss Посмотреть сообщение
Лучше вообще методом Синхронайз не пользоваться,
можете привести аргументы, почему так ? вроде бы нормально работает....

Цитата Сообщение от northener Посмотреть сообщение
Как и классом TThread
альтернатива ?
0
Модератор
 Аватар для FIL
3492 / 2614 / 742
Регистрация: 19.09.2012
Сообщений: 7,977
06.11.2014, 18:48
Не вижу особого смысла в списке FThreads. В данном случае достаточно обычной переменной-счетчика.
Не понятно, что такое:
Delphi
1
2
  if FThreads.count > FMaxThreads then
    TThread(FThreads[FThreads.count-1]).Terminate;
ProgressBar - визуальный компонент, следовательно, работать с ним в доп. потоке надо через методы синхронизации.
ProgressBar можно создавать без промежуточной переменной р.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
06.11.2014, 20:22
Цитата Сообщение от vuasya Посмотреть сообщение
почему так ?
Потому что стоит чуть нагрузить осн.поток, так чтобы он ощутимое время не реагировал на сообщения - и доп.поток застрянет на синхронайзе все то время, пока осн.поток будет занят.

Да и концепуально доп.поток не должен ничего знать о существовании форм и контролов на них, а при синхронайзе появляется неистребимый соблазн сунуть нос дела осн.потока, куда его совать вообще не следует)
0
1 / 1 / 2
Регистрация: 26.08.2013
Сообщений: 381
06.11.2014, 22:11  [ТС]
Цитата Сообщение от FIL Посмотреть сообщение
Не понятно, что такое:
там проверка, если потоков , больше чем задано , то закрываем лишний поток, но вот щас я подумал... как в моем случае организовать ограничение потоков ? ибо я же делаю так :
Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
for i := 0 to memo1.lines.count-1 do begin
 
  t := TRecursiveSearchThread.Create(true);
  with t do
  begin
    Priority := tpLower;
    stran := memo1.lines[i];
    FreeOnTerminate := true;
    OnTerminate := HandleThreadTerminate;
    FThreads.add(t);
    resume;
  end;
  end;
тобишь создаю столько потоков, сколько у меня строк в мемо1 и каждому потоку свою строку даю для обработки. Хочу к примеру ограничить 10 потоками, чтобы все это обрабатывали . Если использовать процедуру HandleFileQueued(self); , о которой я писал выше, то она уничтожит потоки, которые создаются с мемо. Если сделать так :


Delphi
1
2
3
4
5
6
7
8
9
10
11
12
13
14
for i := 0 to memo1.lines.count-1 do begin
HandleFileQueued(self);
  t := TRecursiveSearchThread.Create(true);
  with t do
  begin
    Priority := tpLower;
    stran := memo1.lines[i];
    FreeOnTerminate := true;
    OnTerminate := HandleThreadTerminate;
    FThreads.add(t);
    resume;
 
end;
  end;
Можете подсказать примерно как сделать, чтобы 10 потоков (к примеру) брали след акк по порядку из мемо, при это не брали чужой. Может в HandleThreadTerminate дать сразу новое задание. Хотя ... я чет в тупик попал . Не поможете ?

Добавлено через 13 минут
в принципе ничего страшного нет, что неограниченное кол-во потоков создается. По сути, они же сразу уничтожаются , тем самым освобождая место. Хотя, если будет 10000 строк в мемо... хм..

Добавлено через 6 минут
хотяя.. бред сказал ... можете в нужное русло направить ?
0
Модератор
 Аватар для FIL
3492 / 2614 / 742
Регистрация: 19.09.2012
Сообщений: 7,977
06.11.2014, 22:14
Цитата Сообщение от vuasya Посмотреть сообщение
если потоков , больше чем задано , то закрываем лишний поток
Этот код ничего не закрывает.
Да и с какой стати потоков может стать больше, чем задано, если ты должен контролировать процесс их создания.
Цитата Сообщение от vuasya Посмотреть сообщение
как сделать
В цикле создания потоков проверяй их текущее кол-во и создавай новые только если их кол-во меньше максимально допустимого.
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
06.11.2014, 22:14
Потоков должно быть не больше чем кол-во процессоров (ядер) * кол-во нитей на ядро (гипертрединг)

С каждым потоком должна быть ассоциирована очередь запросов ввода/вывода для передачи ему заданий и возврата результатов их выполнения

Можно и довольно удобно использовать очередь, встроенную в системный механизм потоков - очередь APC.
Помещение элемента в очередь потока осуществляется вызовом QueueUserAPC, в этом случае тело поточной процедуры будет выглядеть примерно так:

while not Terminated do
SleepEx(INFINITE);

Т.е. поток стартует и засыпает в ожидании наличия элементов в очереди.
При обнаружении оных поток пробуждается, исполняет процедуру с параметром (или несколько оных, если в очереди несколько элементов), помещенную в очередь вызовом QueueUserAPC и вновь засыпает.
0
1 / 1 / 2
Регистрация: 26.08.2013
Сообщений: 381
06.11.2014, 22:39  [ТС]
Цитата Сообщение от FIL Посмотреть сообщение
В цикле создания потоков проверяй их текущее кол-во и создавай новые только если их кол-во меньше максимально допустимого.
Delphi
1
2
3
for i := 0 to memo1.lines.count-1 do begin
if i < FMaxThreads then // в данном случае переменная i еще и обозначает номер потока
  t := TRecursiveSearchThread.Create(true);
но не в этом проблема, проблема в том, как заставить поток, по завершению "своего дела" приступить к след строке из мемо1 ....

Цитата Сообщение от mss Посмотреть сообщение
QueueUserAPC
погуглил, но ничего путного не нашел.Может я не так ищу, но примерно понял так :

Delphi
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
// в execute 
procedure TRecursiveSearchThread.Execute;
var
 i: Integer;
   f:Integer;
   CurAcc, TP:integer;
    HTTP:THTTPSend;
    IP, Port:string;
    data:TStringStream;
    HTML:TStringList;
begin
  inherited;
if not Terminated then
  begin
 HTTP:=THTTPSend.Create;
     with HTTP do begin
           MimeType:='application/x-www-form-urlencoded';
      UserAgent:= 'Mozilla/5.0 (Windows; U; Win98; en-US; rv:0.9.2) Gecko/20010726 Netscape6/6.1';
     end;
       HTTP.HTTPMethod('GET',PChar('http://yaca.yandex.ua/yca/cat/'+FStran+'.html?text=101&ncrnd=22&nocookiesupport=yes'));
       if pos('200', HTTP.Headers.Text)<>0 then  begin
       src:=Tstringlist.Create;
      sit2:=Tstringlist.Create;
     src.LoadFromStream(HTTP.Document);
   ParseStr(src.Text, '<h3 class="b-result__head"><a href="http://', '/', sit2);
       flolka:=sit2.Text;
       end;
       http.Free;
       src.Free;
       sit2.Free;
      end;
while not Terminated do
SleepEx(INFINITE);
end;
Цитата Сообщение от mss Посмотреть сообщение
Т.е. поток стартует и засыпает в ожидании наличия элементов в очереди
понять, что поток закончил мы можем по процедуре HandleThreadTerminate , где поток выведет результат, а дальше как дать ему след задание ?
0
3530 / 2270 / 279
Регистрация: 24.12.2010
Сообщений: 13,723
06.11.2014, 22:50
Цитата Сообщение от vuasya Посмотреть сообщение
ничего путного не нашел
Вот
0
Модератор
 Аватар для FIL
3492 / 2614 / 742
Регистрация: 19.09.2012
Сообщений: 7,977
06.11.2014, 23:13
Цитата Сообщение от vuasya Посмотреть сообщение
в данном случае переменная i еще и обозначает номер потока
И как номер потока может быть связан с текущим их количеством?
Цитата Сообщение от vuasya Посмотреть сообщение
как заставить поток... приступить к след строке
В нынешнем варианте - никак. Поток передает результаты своей работы и завершается, а на его место создается след. поток с новым заданием.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
06.11.2014, 23:13

Правильно завершить поток
Прошу помощи людей, хорошо разбирающихся в многопоточности. Из-за зависания формы приложения во время долгого выполнения (не отвечают...

Правильно завершить поток
Здравствуйте!!! Делаю программу через поток. Вот код #include &lt;vcl.h&gt; #pragma hdrstop #include &quot;UTime1.h&quot; ...

Как правильно завершать поток?
есть код: #include &quot;stdafx.h&quot; DWORD WINAPI PoolThread(LPVOID); int _tmain(int argc, _TCHAR* argv) { while(1) { HANDLE...

Как правильно отправить в поток?
Приветы всем. Помогите разобраться с потоками на простом примере. Ситуация бывает такая, при открытии большого количества файлов,...

Как правильно закрыть поток
Доброго времени суток. Не могу закрыть поток в методе. private static int intScaner() { BufferedReader in = new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
95
Ответ Создать тему
Новые блоги и статьи
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
Как ИИ начал спорить и врать (возможно почуяв опасность для себя от индустрии - уход от электроники).
Hrethgir 04.08.2026
Недельный диалог, на фоне событий с НПЗ. Да, из спирта можно получать бензин, и это не сложно. Но потом в схеме я решил избавиться от насоса, при этом полностью сделав контроль подачи спирта в. . .
Термопринтер QR701
Argus19 03.08.2026
Термопринтер QR701 Купил два термопринтера QR701. На сэлф-тесте написано: Language: PC936 (GB18030). Что означает, что принтеры могут печатать только латиницу и китайские иероглифы. Так же. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru