![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Создание потоков
Макака © (2016-03-15 15:48:00)Нужно создать 4 потока
Я правильно понял, для этого достаточно создать 4 класса TThread ?
И правильно ли я понял, что эти 4 потока будут выполняться на разных ядрах?
Макака (2016-03-16 01:49:00) [41]У меня нет в потоках обращения к одним и тем же VCL компонентам, поэтому синхронизация мне не нужна, поэтому 100 процентов дело в распараллеливании.
Макака (2016-03-16 01:36:00) [42]Либо с вероят 90 проц я не правильно распараллелил код (хотя в нём всё выглядит логичным). Единственное в чём я не уверен: создал класс(свой), создал несколько экземпляров, заполнил первый данными, копировал так:
Экземпляр2:= Экземпляр1, этого же достаточно для копирования?
Германн (2016-03-16 00:58:00) [43]
> Короче, я пришёл к таких выводам:
> если создать 1 поток всё работает! и к компонентам формы
> можно обращаться, можно делать всё что угодно.
> Если создать два потока, то работает один из них. Может
> это в вин10 что то?
>
Неправильные выводы. Ну т.е. абсолютно неправильные.
"1 поток" у тебя всегда создан, раз ты написал программу и запустил её. И к компонентам формы можешь обращаться из него без каких-либо ограничений.
Проблемы с дополнительными потоками. Сколько бы их не было. 1, 2, 3 и т.д.
Макака (2016-03-16 00:02:00) [44]Юрий Зотов большое спасибо! Завтра посмотрю твой код.
Короче, я пришёл к таких выводам:
если создать 1 поток всё работает! и к компонентам формы можно обращаться, можно делать всё что угодно.
Если создать два потока, то работает один из них. Может это в вин10 что то?
Игорь Шевченко (2016-03-15 22:00:00) [45]В Demos не судьба посмотреть ?
Rouse_ (2016-03-15 20:07:00) [46]Ах, да забыл, там тебе нитей нужно было, тогда вот этот участок напиши вот так:
{ 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;
Rouse_ (2016-03-15 19:55:00) [47]На вот - с тебя моих потраченных 7 минут.
http://rouse.drkb.ru/tmp/thread.zip
Юрий Зотов (2016-03-15 19:23:00) [48]Этот код должен быть в методе формы, из которой создаются потоки (и на которой лежат Label'ы.
Макака (2016-03-15 19:09:00) [49]Ругается на Self
Юрий Зотов (2016-03-15 18:54:00) [50]В поток надо передать ссылку на форму. Через эту ссылку поток получает доступ к форме и может делать с ней что угодно.
type
TNewThread = class(TThread)
Form: TMyForm;
... // Далее как у Вас
end;
procedure TNewThread.SetSynchronize;
begin
Form.Label1 := 'Обновлено';
end;
Thread_1:=TNewThread.Create(true);
Thread_1.Form := Self;
... // Далее как у Вас
Rouse_ (2016-03-15 18:45:00) [51]Проект заархивируй и ссылку дай, так будет проще
Макака (2016-03-15 18:27:00) [52]Сотрите
Основной код-цикл от 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
sniknik (2016-03-15 18:05:00) [53]если хочешь "счетчик" то в цикле, если конечный результат вывести то потом.
Макака (2016-03-15 17:50:00) [54]Мне нужно в процедуре Update изменять значения Labe-ов ?
Synchronize(Update);
Или их можно в цикле(который выполняет поток) изменить, а потом обновить в Update?
Юрий Зотов (2016-03-15 17:23:00) [55]> для этого достаточно создать 4 класса TThread ?
Класс - один. Экземпляров этого класса - четыре.
> синхронизировать каждый потом с главным потоком
Только обновление Label'ов - см. Synchronize.
Макака (2016-03-15 17:03:00) [56]Далее, у меня в коде цикла записано изменение Label-ов на форме, но почему то меняется только одна группа из рандомного потока.
Теперь мне получается нужно синхронизировать каждый потом с главным потоком проги?
Rouse_ (2016-03-15 16:59:00) [57]можно и так
Макака (2016-03-15 16:55:00) [58]Допустим у меня есть цикл от 1 до 100 с кодом внутри и я хочу разбить его выполнение на 4 потока.
Этот код выношу в отдельную процедуру, в которой на входе указывается 2 числа: от какого до какого выполнять.
Далее создаю 4 потока и в коде Execute каждого потока вставляю ссылку на эту процедуру (например Run(1,25); во втором Run(26,50);
Правильно?
Rouse_ (2016-03-15 15:51:00) [59]Как правило да, но можно системе подсказать как их лучше раскидать вызовом SetThreadAffinityMask(), правда это не значит что она так их распараллелит, только если будет возможность