घर
Top.Mail.Ru Yandeks.Metrika
मंच: "शुरुआती";
वर्तमान संग्रह: 2018.03.04;
डाउनलोड करें: [xml.tar.bz2];

नीचे

धागे बनाना इसी तरह की शाखाएँ खोजें


Макака   (2016-03-15 15:48) [0]

Нужно создать 4 потока
Я правильно понял, для этого достаточно создать 4 класса TThread ?
И правильно ли я понял, что эти 4 потока будут выполняться на разных ядрах?



Rouse_ ©   (2016-03-15 15:51) [1]

एक नियम के रूप में, हाँ, लेकिन आप सिस्टम को बता सकते हैं कि सेटट्रेडएफ़िनिटीमास्क () को कॉल करके उन्हें कैसे बिखेरना सबसे अच्छा है, हालांकि इसका मतलब यह नहीं है कि यह केवल अवसर होने पर उन्हें समानांतर करेगा।



Макака   (2016-03-15 16:55) [2]

Допустим у меня есть цикл от 1 до 100 с кодом внутри и я хочу разбить его выполнение на 4 потока.
Этот код выношу в отдельную процедуру, в которой на входе указывается 2 числа: от какого до какого выполнять.
Далее создаю 4 потока и в коде Execute каждого потока вставляю ссылку на эту процедуру (например Run(1,25); во втором Run(26,50);
है न?



Rouse_ ©   (2016-03-15 16:59) [3]

यह संभव है और ऐसा है



Макака   (2016-03-15 17:03) [4]

Далее, у меня в коде цикла записано изменение Label-ов на форме, но почему то меняется только одна группа из рандомного потока.
Теперь мне получается нужно синхронизировать каждый потом с главным потоком проги?



Юрий Зотов ©   (2016-03-15 17:23) [5]

> для этого достаточно создать 4 класса TThread ?

Класс - один. Экземпляров этого класса - четыре.

> синхронизировать каждый потом с главным потоком

Только обновление Label"ов - см. Synchronize.



Макака   (2016-03-15 17:50) [6]

Мне нужно в процедуре Update изменять значения Labe-ов ?
सिंक्रोनाइज़ (अपडेट);

Или их можно в цикле(который выполняет поток) изменить, а потом обновить в  Update?



sniknik ©   (2016-03-15 18:05) [7]

यदि आप एक "काउंटर" चाहते हैं तो एक लूप में, यदि अंतिम परिणाम आउटपुट है तो बाद में।



Макака   (2016-03-15 18:27) [8]

Сотрите
Основной код-цикл от 1 до 200, в нем изменяются Лейбелы, допустим так Label[i].Caption:=inttostr(i);
Запускается 4 потока


type
 TNewThread = class(TThread)
  I1,I2:integer;
  procedure SetSynchronize;
  protected
  procedure Execute; override;
 end;
var
   Thread_1:TNewThread;
   Thread_2:TNewThread;
   Thread_3:TNewThread;
   Thread_4:TNewThread;
 ...........................
procedure TNewThread.SetSynchronize;
begin
end;

procedure TNewThread.Execute;
begin
Run(I1,I2);
Synchronize(SetSynchronize);
end;
........................................
 Thread_1:=TNewThread.Create(true);
 Thread_1.I1:=0;
 Thread_1.I2:=43;
 Thread_1.FreeOnTerminate:=true;
 Thread_1.Priority:=tpHighest;
 Thread_1.Resume;
//Итак со всеми 4мя.


В I1 I2 указываются границы работа цикла.
Что делаем в SetSynchronize?
Как я думаю: нам нужно объявить список в TNewThread, после того как первый поток прошёл код в цикле до конца, передавать список в TNewThread, и далее в SetSynchronize по списку обновлять TLable



Rouse_ ©   (2016-03-15 18:45) [9]

प्रोजेक्ट को आर्काइव करें और लिंक दें, यह आसान हो जाएगा



Юрий Зотов ©   (2016-03-15 18:54) [10]

В поток надо передать ссылку на форму. Через эту ссылку поток получает доступ к форме и может делать с ней что угодно.

type
TNewThread = class(TThread)
 Form: TMyForm;
 ... // Далее как у Вас
end;

procedure TNewThread.SetSynchronize;
begin
 Form.Label1 := "Обновлено";
end;

Thread_1:=TNewThread.Create(true);
Thread_1.Form := Self;
 ... // Далее как у Вас



Макака   (2016-03-15 19:09) [11]

Ругается на Self



Юрий Зотов ©   (2016-03-15 19:23) [12]

यह कोड फॉर्म मेथड में होना चाहिए, जहां से धाराएं बनाई गई हैं (और जिस पर लेबल का झूठ है।



Rouse_ ©   (2016-03-15 19:55) [13]

На вот - с тебя моих потраченных 7 минут.
http://rouse.drkb.ru/tmp/thread.zip



Rouse_ ©   (2016-03-15 20:07) [14]

Ах, да забыл, там тебе нитей нужно было, тогда вот этот участок напиши вот так:

{ TNewThread }

var
 ThreadIndex: Byte = 0;

constructor TNewThread.Create(AOwnerLabel: TLabel; A, B: Integer);
begin
 inherited Create(False);
 FA := A;
 FB := B;
 FOwnerLabel := AOwnerLabel;
 FreeOnTerminate := True;
 Priority := tpHigher;
 SetThreadAffinityMask(Handle, 1 shl ThreadIndex);
end;

...

procedure TForm1.FormCreate(Sender: TObject);
begin
 DoubleBuffered := True;
 TNewThread.Create(Label1, 0, 25000);
 Inc(ThreadIndex);
 TNewThread.Create(Label2, 26000, 50000);
 Inc(ThreadIndex);
 TNewThread.Create(Label3, 51000, 75000);
 Inc(ThreadIndex);
 TNewThread.Create(Label4, 75000, 100000);
end;



Игорь Шевченко ©   (2016-03-15 22:00) [15]

В Demos не судьба посмотреть ?



Макака   (2016-03-16 00:02) [16]

Юрий Зотов большое спасибо! Завтра посмотрю твой код.
Короче, я пришёл к таких выводам:
если создать 1 поток всё работает! и к компонентам формы можно обращаться, можно делать всё что угодно.
Если создать два потока, то работает один из них. Может это в вин10 что то?



Германн ©   (2016-03-16 00:58) [17]


> Короче, я пришёл к таких выводам:
> если создать 1 поток всё работает! и к компонентам формы
> можно обращаться, можно делать всё что угодно.
> Если создать два потока, то работает один из них. Может
> это в вин10 что то?
>

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



Макака   (2016-03-16 01:36) [18]

Либо с вероят 90 проц  я не правильно распараллелил код (хотя в нём всё выглядит логичным). Единственное в чём я не уверен: создал класс(свой), создал несколько экземпляров, заполнил первый данными, копировал так:
Экземпляр2:= Экземпляр1, этого же достаточно для копирования?



Макака   (2016-03-16 01:49) [19]

मेरे पास धागे में समान VCL घटकों तक पहुंच नहीं है, इसलिए मुझे सिंक्रनाइज़ेशन की आवश्यकता नहीं है, इसलिए 100 प्रतिशत समानांतरकरण के बारे में है।



popcorn++   (2016-03-16 03:14) [20]

मॉडरेटर द्वारा हटा दिया गया



sniknik ©   (2016-03-16 08:38) [21]

> У меня нет в потоках обращения к одним и тем же VCL компонентам, поэтому синхронизация мне не нужна,
тебе может и нет, а программе нужна.

> поэтому 100 процентов дело в распараллеливании.
дело всегда в прокладке.



Юрий Зотов ©   (2016-03-16 09:22) [22]

> Макака   (16.03.16 01:36) [18]

> создал несколько экземпляров, заполнил первый данными, копировал так:
> Экземпляр2:= Экземпляр1, этого же достаточно для копирования?

Нет. Любая объектная переменная по сути есть указатель, ссылка на объект. Сам объект лежит где-то в динамической памяти, а ссылка лишь хранит его адрес.

Поэтому Вы копируете не объект, а его адрес. То есть, обе переменные (и Экземпляр1, и Экземпляр2) у Вас указывают на один и тот же поток.



Rouse_ ©   (2016-03-16 10:09) [23]


> Макака (16.03.16 01:49) [19]

Ну ты код для начала посмотри, который я тебе написал выше, все вопросы отпадут.



Макака   (2016-03-16 12:19) [24]

सब कुछ तब हुआ जब मैंने कक्षा के उदाहरणों को सही ढंग से कॉपी किया।



Макака   (2016-03-16 12:20) [25]

आप सभी को धन्यवाद!



Макака   (2016-03-16 14:15) [26]

अभी भी इस तरह के एक सवाल, क्या कोई dll है, क्या मैं इसे 4 विभिन्न थ्रेड्स में चला सकता हूं?



Юрий Зотов ©   (2016-03-16 14:27) [27]

> Макака   (16.03.16 14:15) [26]

1. Запускается не DLL, а функции из нее.
2. Можно, если в DLL нет специальных препятствий для этого.



Макака   (2016-03-16 14:29) [28]

4 dll, और 4 प्रत्येक में निर्यात के लिए अलग-अलग फ़ंक्शन बनाए, केवल इसी ने काम किया



Макака   (2016-03-16 15:08) [29]

और यह कैसे सुनिश्चित करें कि सभी 4 थ्रेड्स के पूरा होने के बाद, कोड निष्पादित किया जाता है?



Inovet ©   (2016-03-16 15:14) [30]

> [29] Макака   (16.03.16 15:08)

Обяснили же: есть основной поток, который запускает остальные. Вот он пусть ждёт завершения и дальше делает ещё что-то.



Inovet ©   (2016-03-16 15:15) [31]

प्रत्येक थ्रेड के लिए एक अलग DLL के साथ - स्टाइल क्या है? मेरी राय में चीनी।



Макака   (2016-03-16 15:24) [32]

Inovet это я прекрасно понял) а как это сделать?
Можно написать так Sleep(замерить макс время выполнения и написать сюда);
пойду погуглю ещё



Inovet ©   (2016-03-16 15:32) [33]

> [32] Макака   (16.03.16 15:24)
> а как это сделать?

WaitForMultipleObjects



Макака   (2016-03-16 16:54) [34]

WaitForMultipleObjects и как он работает?)
делаю так, на 4 потока:

var  Handles : array of Cardinal;
..................
SetLength(Handles,4);
Thread_1:=TNewThread.Create(true);
 Handles[0]:=Thread_1.Handle;
 Thread_1.FreeOnTerminate:=true;
 Thread_1.Priority:=tpNormal;
 Thread_1.I1:=0;
 Thread_1.I2:=51;
 Thread_1.TreadNumb:=0;
 Thread_1.Resume;
...............................итак со всеми
 if (WaitForMultipleObjects(4,@Handles,true,infinite) = 1) then
     ShowMessage("Всё, приехали!");



Юрий Зотов ©   (2016-03-16 17:20) [35]

हैंडल अनिवार्य रूप से एक पॉइंटर हैं। इसलिए, @ हैंडल्स एक सूचक का पता है, लेकिन एक सरणी नहीं है। लेकिन @Handles [0] सरणी का पता है।



Inovet ©   (2016-03-16 17:40) [36]

> [34] Макака   (16.03.16 16:54)
> if (WaitForMultipleObjects(4,@Handles,true,infinite) = 1)

Зачем 1? Вот здесь смотри символьные значения возврата
https://msdn.microsoft.com/en-us/library/windows/desktop/ms687025%28v=vs.85%29.aspx



Макака   (2016-03-16 18:07) [37]


if (WaitForMultipleObjects(4,@Handles[0],true,infinite) = WAIT_OBJECT_0) then
     ShowMessage("Всё, приехали!");

Молчит



Макака   (2016-03-16 18:21) [38]

изменил тип массива на
Handles : array of THandle;
заговорила)
Но на этом приключения не закончились, до момента "приехали" виснет приложение.



Макака   (2016-03-16 18:22) [39]

нужно ещё один поток создавать?



sniknik ©   (2016-03-16 18:37) [40]

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

— Эх, эх... — сказал гость, морщась.
— А  вам, что же, мои  стихи не  нравятся?  — с любопытством  спросил Иван.
— Ужасно не нравятся.
— А вы какие читали?
— Никаких я ваших стихов не читал! — нервно воскликнул посетитель.
— А как же вы говорите?
— Ну, что  ж тут  такого, — ответил  гость, — как будто я  других не читал? Впрочем...  разве что чудо? Хорошо,  я готов  принять на веру. Хороши ваши стихи, скажите сами?
— Чудовищны! — вдруг смело и откровенно произнес Иван.
— Не пишите больше! — попросил пришедший умоляюще.
— Обещаю и клянусь! — торжественно произнес Иван.



Макака   (2016-03-16 19:09) [41]

आप शायद इसे एक टाइमर के माध्यम से कर सकते हैं। एक चर बनाएँ, और धारा पूरा होने पर 1 पर इसे बढ़ाएँ।



Rouse_ ©   (2016-03-16 19:16) [42]

क्या आप अपना कोड पूरी तरह से दिखा सकते हैं? और फिर यहां बैठो, कॉफी के मैदान का अनुमान लगाएं जिसमें आपने प्रवेश किया था



sniknik ©   (2016-03-17 08:40) [43]

а как же тогда интрига? долгие псевдоинтелектуальные вопросы ни о чем? не, код не нужен.

- А Скрипач не нужен, родной. Он только лишнее топливо жрёт.



Юрий Зотов ©   (2016-03-17 10:11) [44]

> до момента "приехали" виснет приложение

Оно не виснет. Оно ждет завершения всех потоков. Вы же сами вызвали WaitForMultipleObjects - вот оно и ждет.



Юрий Зотов ©   (2016-03-17 10:22) [45]

А чтобы не "висло", можно сделать так - вместо INFINITE поставить разумный интервал (например, 1 сек) и вызывать WaitForMultipleObjects в цикле:

while WaitForMultipleObjects(4, @Handles[0], true, 1000) = WAIT_TIMEOUT do
 Application.ProcessMessages;



sniknik ©   (2016-03-17 10:57) [46]

> while WaitForMultipleObjects(4, @Handles[0], true, 1000) = WAIT_TIMEOUT do
>  Application.ProcessMessages;
?
не учите плохому... он же именно так и "собезьяничает".

если появилась нужда в подобном коде, то смысл вообще в потоке/потоках? просто делай действие прямо там, в основном. время выполнения и будет "ожиданием". ну подвиснет интерфейс чуток, ну и что?
поток нужен если требуется параллельно что-то делать, ждать в это "что-то" не входит.
"проблемы" с интерфейсом несущественны, только ради этого "эстетство" разводить - впустую тратить время.



Юрий Зотов ©   (2016-03-17 11:29) [47]

> स्निकनिक © (17.03.16 10: 57) [46]

Не вижу ничего плохого. Это не таймер, который бессмысленно расходует процессорное время, а нормальное ожидание завершения всех задач.

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

Именно. Есть N задач, которые могут выполняться параллельно, но приложение не должно продолжать свою работу, пока не завершатся все эти задачи. Соответственно, главный поток порождает N вторичных потоков и ждет их завершения.

Похоже на задачу массового обслуживания: в магазине есть N продавцов и магазин не должен закрываться, если хотя бы один продавец еще занят.

Пример из реальной практики. Невизуальное приложение обрабатывает информацию от нескольких терминалов сбора данных. Главный поток слушает подключение терминала и, обнаружив его, порождает поток обработки данных от этого терминала, а сам продолжает прослушку.

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

Приблизительно по этой схеме (на самом деле сложнее, но это сейчас неважно) была написана служба для одного из подмосковных предприятий.



эндсоувот ©   (2016-03-17 11:36) [48]

а нормальное ожидание завершения всех задач.

нормальное будет через MsgWaitForMultipleObjects

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

Если ждать - потоки не нужны.
Если потоки нужны, то их не надо ждать.
Расскажите им про хендл нужного окна и потоки сами скажут когда они завершили работу.



Юрий Зотов ©   (2016-03-17 11:46) [49]

> через MsgWaitForMultipleObjects

Согласен, но цикл и ProcessMessages при этом все равно останутся.

> хендл нужного окна

1. Окна может и не быть.
2. Потребуется синхронизация.



эндсоувот ©   (2016-03-17 12:01) [50]

пример разумного использования потоков без ожиданий синхронайзов и прочих колхозов:

цб публикует данные для неких форм.
сервис устроен таким образом, что нельзя "одним запросом вынуть все".
можно только по частям, для которых есть ~три-четыре критерия дробления.

इस तरह से:
в главном инициируется структура с описанием "чего надо вынуть"
далее генерятся начальные скажем пять потоков, которые достают каждый по одной порции.
родившись, поток шлет сообщение окну в котором запрашивает параметры очередной порции данных, затем лезет в веб, получает данные, отдает их очереди sql-потока и дальше снова сигнализирует окну вопросом: "есть чо делать?"
если есть, то все повторяется, если нет, поток убивается об стену.

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

если теперь в эту грациозную, элегантную и совершенную схему впендюрить вэйты, то либо ничего хорошего не получится, либо будет такой спагетти-код, что атас, война и немцы.



sniknik ©   (2016-03-17 12:14) [51]

> 1. Окна может и не быть.
но управляющий процесс/поток то есть? т.что PostTreadMessage в общий канал управления
> а сам продолжает прослушку.
здесь и поймает

> 2. Потребуется синхронизация.
зачем? простой счетчик работающих потоков, инкримент перед стартом, декремент по сообщению о завершении из самого потока.

> Тогда, получив команду на завершение
либо завершается если счетчик работающих = 0, либо взводит "флаг" на завершение по которому
> перестает порождать новые потоки
и завершается по достижению счетчиком нуля.

никакой синхронизации, и ожиданий не требуется, все в стиле "событие -> реакция".



Юрий Зотов ©   (2016-03-17 12:25) [52]

> и завершается по достижению счетчиком нуля.

Вот именно ЭТО и означает: ЖДАТЬ обнуления счетчика.



эндсоувот ©   (2016-03-17 12:29) [53]

"ждать" понятие растяжимое.

юзер ничего не делающий и глазеющий на форму тоже как бы "ждет".

а вопрос лишь в том, что в это время происходит "под формой"

если там крутится цикл while wait.... то понятно, что сделать что-либо еще программист сейчас не может. хотя все кнопки и нажимются

а если цикла нет, то у нас доступно все



sniknik ©   (2016-03-17 12:35) [54]

> Вот именно ЭТО и означает: ЖДАТЬ обнуления счетчика.
нет, т.к. никаких функций ожиданий/псевдоожиданий([45]) в коде нет, есть обработчик событий с реакцией на них.
разница однако...

> в магазине есть N продавцов и магазин не должен закрываться, если хотя бы один продавец еще занят.
по этой, же аналогии:
ожидание: охранник закрывающий магазин "втыкает" на продавцов, ждет в общем (весело если кассы сильно разнесены).
событие: выключение последней кассы оповещает охранника (звонок в магазине), который может заниматься чем угодно вместо "втыкания", но по звонку идет и закрывает магазин.



Макака   (2016-03-17 17:38) [55]

Смысл в том, что когда мы нажимаем на кнопку расчёты появляется полупрозрачная панелька с гифкой и надписью "ожидайте"(чтобы гифка не зависала, нужно чтобы форма не висла), далее запускаются 4 потока и производятся расчёты, после их завершения обновляются компоненты на форме и панель прячется.
Вчера реализовал по "колхозному" через таймер.
Сегодня буду разбираться что выше написано, понять как нужно сделать (без колхоза).



Inovet ©   (2016-03-17 20:37) [56]

> [55] Макака   (17.03.16 17:38)
> далее запускаются 4 потока и производятся расчёты, после
> их завершения обновляются

Тогда надо
1. Отдавать потокам (нитям) порции небольшого размера, менее вся_порция/число_потоков.
2. В вызывающей нити распределять остатки, в разумных пределах, чтобы не уйти в бесконечность.;)

И тогда следует юзать
WaitForMultipleObjects
с анализом - кто там завершился и подкидкой ему новой порции.



Eraser ©   (2016-03-17 21:08) [57]

Ждать завершения потока/ов нужно в OnTerminate, который выполняется в контексте главного потока приложения.

Никакие таймеры и циклы ожидания тут не нужны, это лишнее для данной задачи. Лезть со своими "ожиданиями" в цикл выполнения основного потока допустимо только в случае крайней необходимости.



NoUser ©   (2016-03-18 00:13) [58]

>  Лезть со своими "ожиданиями" в цикл выполнения основного
> потока допустимо только в случае крайней необходимости.

ага, например, мышь неожиданно жмякнула крестик.

Поэтому [45] учитывая [55] для ТС самое оно.


> [54] > событие: выключение последней кассы

а кто определит, что она последняя?



sniknik ©   (2016-03-18 01:01) [59]

сама и определит, ее же закрывают, снимают z-отчет. что само по себе событие... выше про счетчик почитай.
не нужно плодить сущности.



पन्ने: 1 2 पूरी शाखा

मंच: "शुरुआती";
वर्तमान संग्रह: 2018.03.04;
डाउनलोड करें: [xml.tar.bz2];

ऊपर









मेमोरी: 0.81 एमबी
समय: 0.04 c
15-1470376172
p
2016-08-05 08:49
2018.03.04
रोड मैप Embarcadero


2-1458046128
अफ्रीका का लंगूर
2016-03-15 15:48
2018.03.04
धागे बनाना


2-1456839307
सलाहकार
2016-03-01 16:35
2018.03.04
Android बनाम Win7


2-1456844768
Mishan
2016-03-01 18:06
2018.03.04
एसक्यूएल सवाल


2-1458382160
Valya
2016-03-19 13:09
2018.03.04
TreeView बहु का चयन करें





अफ्रीकी अल्बानियन अरबी भाषा अर्मेनियाई आज़रबाइजानी बस्क बेलारूसी बल्गेरियाई कैटलन सरलीकृत चीनी) चीनी पारंपरिक) क्रोएशियाई चेक डेनिश डच अंग्रेज़ी एस्तोनियावासी फिलिपिनो फिनिश फ्रेंच
गैलिशियन् जॉर्जियाई जर्मन यूनानी हाईटियन यहूदी हिंदी हंगरी आइसलैंड का इन्डोनेशियाई आयरिश इतालवी जापानी कोरियाई लात्वीयावासी लिथुआनियाई मेसीडोनियन मलायी मोलतिज़ नार्वेजियन
फ़ारसी पोलिश पुर्तगाली रोमानियाई रूसी सर्बियाई स्लोवाक स्लोवेनियाई स्पेनिश स्वाहिली स्वीडिश थाई तुर्की यूक्रेनी उर्दू वियतनामी वेल्श यहूदी बंगाली बोस्नियाई
सिबुआनो एस्पेरांतो गुजराती हौसा हमोंग ईग्बो जावानीस कन्नड़ खमेर लाओ लैटिन माओरी मराठी मंगोलियन नेपाली पंजाबी सोमाली तामिल तेलुगु योरूबा
ज़ुलु
Английский Французский Немецкий Итальянский Португальский Русский Испанский