Форум: "Начинающим";
Текущий архив: 2018.03.04;
Скачать: [xml.tar.bz2];
ВнизСоздание потоков Найти похожие ветки
← →
Макака (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;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.003 c