Консультация № 170771
24.07.2009, 23:34
0.00 руб.
0 25 2
Здравствуйте!
У меня такой вопрос: как в Delphi 7 работать с потоками ? Я прочитал много материала по этому, но у меня не получилось создать свой поток и запустить его, поэтому я прошу найти либо хорошую статью на эту тему, либо (даже лучше) готовый пример.
Буду очень признателен!

Обсуждение

давно
Студент
15716
139
24.07.2009, 23:40
общий
это ответ
Здравствуйте, AkaProc.

Лучше чем вот эта статья я не встречал, там есть примеры:_http://forum.vingrad.ru/forum/topic-60076.html
5
Огромное спасибо!
Неизвестный
25.07.2009, 00:22
общий
это ответ
Здравствуйте, AkaProc.
вот пример простенького потока

Type
TMyThread = class(TThread)
protected
procedure Execute; override;
public
constructor Create;
destructor Destroy; override;
end;

var
Th:TMyThread;

implementation

constructor TMyThread.Create;
begin
//событие возникает при создании потока
inherited Create(True);
FreeOnTerminate:=True;
Resume;
end;

destructor TMyThread.Destroy;
begin
inherited Destroy;
//событие возникает при разрушении потока
end;

procedure TMyThread.Execute;
begin
//Код который нужно выполнить в потоке
end;

// Th:=TMyThread.Create;//Создать поток
// Th.Terminate;//Остановить поток
// Th.Suspend;//Приостановить поток
// Th.Resume;//Продолжить
5
Неизвестный
25.07.2009, 00:34
общий
У меня проблема в том, что когда я пытаюсь связать переменную со своим потоком, т.е. пишу NewThread: MyTread, где MyTread - это имя моего потока (то, что я вписываю в форму, когда создаю модуль с потоком), NewThread - переменная для связи. Проблема в том, что он говорит, что не знает, что такое MyThread. Бьюсь уже много времени, Вы не знаете, с чем может быть связано?
Неизвестный
25.07.2009, 00:55
общий
В моем примере переменная для связи с потоком "Th"
с помощью ее и управляете потоком
Th:=TMyThread.Create;//так запускать поток
Th.Terminate;//так остановить
//вот мой пример

возможно я не понял вопроса
тогда вместо MyThread напишите TMyThread
var NewThread : TMyThread; //опишите NewThread как глобальную переменную
NewThread:=TMyThread.Create;//создать и запустить поток

давно
Студент
15716
139
25.07.2009, 01:03
общий
В uses модуль где описан поток вписан?
давно
Студент
15716
139
25.07.2009, 01:20
общий
Может весь исходник выложите, так будет проще.
давно
Студент
15716
139
25.07.2009, 01:41
общий
Ну так там вроде нет ошибок, нормально компилируеться код.
давно
Мастер-Эксперт
425
4118
25.07.2009, 05:18
общий
AkaProc:
Цитата: Из вопроса
но у меня не получилось создать свой поток и запустить его...

Проблема в том, что он говорит, что не знает, что такое MyThread.

1. Вы по-русски опишите более подробно, что Вы имеете в виду под "запуском потока".
2. "NewThread: MyTread" - NewThread - это имя переменной, которой Вы будете в дальнейшем манипулировать в своей программе, а то что пишется после двоеточия - это тип Вашей переменной, который должен быть описан либо в стандартных типах языка, либо объявлен после служебного слова Type в Вашей программе или в одном из подключенных модулей в секции Interface.
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
25.07.2009, 14:50
общий
У меня не получалось "связать" переменную со своим потоком, с помощью которой я мог бы управлять им.
VolRus, Ваш пример мне понравился, только кнопка "остановить поток" почему-то не работает, я выяснил это, сделав простой счетчик, который считает от 1 до бесконечности и выводит цифры в заголовок формы.
Вот ссылка на модификацию Вашего примера: Скачать .
И еще: я заметил, что у Вас все в одном модуле (юните) написано, а у меня было в двух: в одном описание потока, которое генерировал редактор, в которое надо было вставлять код потока и основной, т.е. там, где описываются события нажатия кнопок и тд. Так, вот, проблема была в том, что я не мог установить связь со своим потоком.
Вот ссылка на мой проект: Скачать
Неизвестный
25.07.2009, 19:08
общий
Ваш проект не работает потому что модуль (unit2) объявлен после implementation (и это правильно в даном случае)
а переменная Htr:MyThread перед.
Мой совет объявлять переменную в одном модуле с классом ТMyThread.
И еще плохой стиль программирования когда в имени типа или класса первая буква не "Т" например (MyThread --> TMyThread).
Вот немножко подправил ваш проект MyThread.rar

Неизвестный
25.07.2009, 19:19
общий
Громадное спасибо! :)
Кстати, если я нажму на кнопку "Стоп (нерекомендовано)", то ничего не происходит - поток не останавливается - это нормально?
Неизвестный
25.07.2009, 19:42
общий
Это нормально.
Terminate это аварийное завершение потока не всегда работает корректно.
Лучше что-бы поток сам завершался.
давно
Студент
15716
139
25.07.2009, 19:48
общий
в самом потоке должна быть проверка что то типа
if not Terminated
иначе потоку все равно что вы вызвали Termnate

// Забыл буковку :)
Неизвестный
25.07.2009, 20:55
общий
Благодарю!
Я написал "if not terminated", т.к. если написать "if not terminate", то он выдает ошибку. Да, действительно, если поставить это условие, то все отлично работает. Еще я добавил кнопки "пауза" и "продолжить". Чтобы сделать паузу надо написать: "suspend", чтобы продолжить - "resume", есстественно, все управление идет через переменную.
Большое спасибо за помощь!
давно
Мастер-Эксперт
425
4118
26.07.2009, 03:22
общий
AkaProc:
Когда Вы запускаете отдельный поток, то Вы расчитываете, что в этом потоке выполнится какая-то отдельная задача. Нужно ли делать так, чтобы эта задача прерывалась на какой-то стадии, при этом непонятно, что сделано, а что нет? Думаю, что не нужно. Отсюда вывод - поток - это не мультимедиа-плейер, который захотел запустил, захотел - остановил, поток - эта какая-то вполне определённая отдельная задача (например, форматирование диска С: ), которую если запускать в рамках основного потока приложения, то она будет это приложение тормозить, а если запускать её в отдельном потоке, то Вы получите реальную многозадачность. Вот из этого критерия и исходите, когда планируете завести отдельный поток. Т.е. поток сам по себе не имеет никакой ценности, так же как Вы купили себе BMW, поставили его на стоянку и ничего с ним не делаете. Согласитесь, это бессмыслица. В отдельном потоке всегда выполняется какая-то вполне определённая задача, поэтому запуск и остановка потока должны происходить исключительно в логическом контенте этой задачи.
Ещё как пример. Построили Вы у себя на даче теплицу и назвали её "MyThread". Она Вам нужна просто так, отдельно стоящая? Явно нет. Открываете Вы её, потом закрываете - никакой практической пользы в этом не будет. А вот когда Вы высадите в эту теплицу рассаду помидоров, вот тогда работа с теплицей "MyThread" приобретает реальный практический смысл - днём Вы её открываете, чтобы туда попадал солнечный свет и помидоры хорошо росли, вечером закрываете, чтобы из теплицы ночью не уходило тепло и т.д. Понимаете теперь зачем нужны потоки?
Об авторе:
Я только в одном глубоко убеждён - не надо иметь убеждений! :)
Неизвестный
27.07.2009, 14:27
общий
Да, конечно, я понимаю, зачем они нужны. Дело в том, что у меня программа, в которой есть процедура, которая выполняется 50 минут. Причем, у меня процессор Е8400.Вот я и решил выполнять ее в виде отдельного потока, чтобы при этом можно было работать с программой, а не ждать эти 50 минут пока она "отвиснет". А то, что я написал ранее - это просто команды, с помощью которых можно управлять потоком. Есстесственно, завершаться поток будет только после выполнения задачи.
Неизвестный
28.07.2009, 16:15
общий
Кстати, а не подскажете, как сделать, если мне надо передать параметры при запуске потока, например, значения каких-нибудь переменных, т.е. мне надо передать значения переменных в процедуру (Rasschet) и запустить ее в отдельном потоке?
Я намутил тут много чего и у меня все равно выдается ошибка в объявлении процедуры. Можете посмотреть программу? Буду ОЧЕНЬ признателен!
Тут проект с "экспериментами": Тут пытался сделать отдельный поток
Тут "чистый" проект, т.е. проект, где процедура Rasschet не запускается отдельном потоке, а работает в общем: Тут проект без потоков
Спасибо!
Неизвестный
28.07.2009, 16:29
общий
TMyThread = class(TThread)
protected
value1:integer;
value2:string;
procedure Execute; override;
public
constructor Create(v1:integer;v2:string);
...
end;

constructor TMyThread.Create;
begin
v1:=value1;
v2:=value2;
inherited Create(True);
FreeOnTerminate:=True;
Resume;
end;

procedure TMyThread.Execute;
begin
Rasschet(v1,v2);
end;

//использовать так
MyThread:=TMyThread.Create(переменная1, переменная2);
Неизвестный
28.07.2009, 19:58
общий
Огромное спасибо, все получилось! :)
Неизвестный
28.07.2009, 21:02
общий
Если вы не против, у меня еще маленький вопросик:
у меня строка: form1.PG.position:=int(((-10)/u)*1000);
где PG - это прогрессбар, который находится на форме
Вопрос: дело в том, что он ругается что тип Extended не сочитается с типом Integer, который необходим для прогрессбара. Как можно преобразовать мое значение выражение типа Extended в целое число типа Integer ?
Спасибо.
давно
Студент
15716
139
28.07.2009, 21:36
общий
form1.PG.position := Round(((-10)/u)*1000);
Неизвестный
28.07.2009, 21:44
общий
Я Вам бесконечно благодарен! :)
Неизвестный
28.07.2009, 21:58
общий
я так и не понял что делает эта ваша формула
используйте вместо Int, round или trunc
Round(12.75) = 13 //Функция Round округляет число с плавающей точкой в целое число.
Trunc(12.75) = 12 //Функция Trunc возвращает целочисленную часть числа с плавающей точкой, как число целое число.
Int(12.75) = 12 //Функция Int возвращает целочисленную часть числа с плавающей точкой, как число с плавающей точкой. (для прогрес бара нужно целое число)
Frac(12.75) = 0.75 //Функция Frac возвращает дробную часть числа с плавающей точкой, как число с плавающей точкой.
Неизвестный
28.07.2009, 22:00
общий
а вижу вы уже сделали

мне не составит особого труде еще помочь
Неизвестный
29.07.2009, 00:00
общий
Я переделал эту формулу, теперь выглядит так: form1.PG.position:=round((chet/10.6)*100); Chet - это переменная, которая увеличивается с заданным шагом. Это индикатор прогресса. Дело в том, что сначала мучился, как же сделать прогрессбар для программы, где у нас есть переменная U, которая меняется с определенным шагом в диапазоне от 0,6 до -10. Потом поставил исскусственный счетчик, который увеличивается с каждым разом прохождения цикла от нуля на заданный пользователем шаг до предела, который равен 10,6, т.к. -10 - 0,6 по модулю равно 10,6 (этот шаг равен шагу, на который уменьшается наша основная переменная (U) и теперь не парюсь.Надеюсь, понятно объяснил. :)
Форма ответа