Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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.002 c
2-1457077794
Dmk
2016-03-04 10:49
2018.03.04
Биты


2-1456752598
Макака
2016-02-29 16:29
2018.03.04
Проверка условий


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


15-1470691802
Юрий
2016-08-09 00:30
2018.03.04
С днем рождения ! 9 августа 2016 вторник


2-1458046128
Макака
2016-03-15 15:48
2018.03.04
Создание потоков





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский