Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2018.03.04;
Скачать: CL | DM;

Вниз

Создание потоков   Найти похожие ветки 

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

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


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

Как правило да, но можно системе подсказать как их лучше раскидать вызовом SetThreadAffinityMask(), правда это не значит что она так их распараллелит, только если будет возможность


 
Макака   (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-ов ?
Synchronize(Update);

Или их можно в цикле(который выполняет поток) изменить, а потом обновить в  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]

Этот код должен быть в методе формы, из которой создаются потоки (и на которой лежат Label"ы.


 
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]

Ещё такой вопрос, есть длл, можно её запустить в 4 разных потоках?


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

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

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


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

создал 4 дллки, и 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 - это, по сути, указатель. Поэтому @Handles - это адрес указателя, но не массива. А вот @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]

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

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



Страницы: 1 2 вся ветка

Текущий архив: 2018.03.04;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.007 c
2-1456752598
Макака
2016-02-29 16:29
2018.03.04
Проверка условий


2-1456844768
Мишаня
2016-03-01 18:06
2018.03.04
Вопрос по SQL


2-1458222695
Новичок
2016-03-17 16:51
2018.03.04
Юниты


2-1458036962
Макака
2016-03-15 13:16
2018.03.04
Очистить множество


15-1470376172
p
2016-08-05 08:49
2018.03.04
Road Map эмбаркадеро