Потоки в DelphiОрганизация многопоточной работы в Delphi |
Уроки Delphi
1. Первая программа
2. Использование компонентов
3. События Delphi
4. Типы данных Delphi
5. Создание своих типов данных
6. Выражения и операторы
7. Работа с файлами в Delphi
8. Дополнительные формы
9. Подпрограммы в Delphi
10. Исключительные ситуации
11. Взаимодействие приложения с пользователем
12. Указатели в Delphi
13. Обзор компонентов
14. Работа со строками
15. Создание интерфейса
16. Графика в Delphi
17. Многопоточность в Delphi
18. Динамическое создание
компонентов Поиск по сайту Это важно:
Метод Application.ProcessMessages;
Это полезно:
Параметр Sender в обработчиках событий;
Бояться не надо |
Потоки в Delphi выполняют функцию имитации псевдопараллельной работы приложения. Как известно, для организации многозадачности операционная система выделяет каждому приложению, выполняющемуся в настоящий момент, определённые кванты времени, длина и количество которых определяется его приоритетом. Поэтому объём работы, который приложение может выполнить, определяется тем, сколько таких квантов оно сможет получить в единицу времени. Для операционной системы каждый поток является самостоятельной задачей, которой выделяются кванты времени на общих основаниях. Поэтому приложение Delphi, умеющее создать несколько потоков, получит больше времени операционной системы, и соответственно сможет выполнить больший объём работы. File -> New -> Other... В появившейся табличке выбора найдём TThread Object. Появится окошко, в верхнюю строку которого (Class Name) введём имя нашего будущего потока: MyThread. В результате будет создан модуль, содержащий заготовку кода, реализующего дополнительный поток Delphi:
unit Unit2; // Имя модуля, содержащего поток. При сохранении его можно изменить.
2. В первом способе класс MyThread был создан мастером в дополнительном модуле. Второй способ состоит в том, что мы сами создаём такой класс в рамках одного из уже существующих модулей программы, например, в модуле Unit1:
unit Unit1; //Обычный модуль в котором описывается основная программа Применение потоковЕсли в основной программе попробовать выполнить такой цикл:while True do; то приложение зависнет. А теперь поместите его в процедуру Execute. При нажатии на кнопку наш бесконечный цикл будет непрерывно выполняться в потоке, однако и приложение как целое не зависнет. В предыдущем примере поток выполняет бесконечный цикл. Однако, поток также обладает возможностями, позволяющими из основной программы передать ему приказ прекратить работу. Метод потока Terminate устанавливает свойство Terminated потока в True. Анализируя это свойство, поток может понять, что он должен завершить работу. Пример:
procedure TMyThread.Execute;
Этот код выполняет бесконечный цикл. Однако, при выполнении в основной программе оператора
MyThread.Terminate;
цикл завершается, и поток прекращает свою работу.При работе с потоками необходимо учитывать приоритет создаваемых потоков. Так, если в предыдущем примере запустить не один поток, а два или больше, нажав на кнопку несколько раз, то компьютер станет очень заметно "тормозить". Это происходит потому, что приоритет по умолчанию новых потоков - нормальный. Можно уменьшить его, задав MyThread.Priority:=tpLower; Этого достаточно, чтобы компьютер чувствовал себя более свободно. Вот таблица приоритетов:
Вот вам готовый проект работы c потоками, для экспериментов. В продолжение темы нужно рассмотреть Особености взаимодействия потоков с объектами VCLДело в том, что при работе с несколькими потоками в приложении необходимо гарантировать, что в данный момент только один из потоков может иметь доступ к свойствам и методам объекта VCL - визуального компонента Delphi. Для обеспечения этого условия в Delphi имеется специальный метод, в рамках которого и нужно вызывать процедуры, модифицирующие свойства и использующие методы визуальных компонентов. читать далее...Графика в Delphi
В начало урока
Следующий урок Вопросы и комментарии (35) Решение задач в Delphi
Грубиян, добавлено 25.08.11, 18:59:35
Ну так и чего мы этим добились? Вы покажите, как ИСПОЛЬЗОВАТЬ поток! Автор, добавлено 26.08.11, 09:25:04 Ну естественно, урок недописан. Всё некогда. Спасибо за напоминание. Автор, добавлено 27.08.11, 20:19:23 Ну вот, дописан вариант создания потока вручную. Теперь нужно пояснить особенности работы потоков с объектами VCL - визуальными компонентами Delphi. Студент , добавлено 4.10.11, 17:40:26 Очень хорошие уроки,спасибо вам многое понял,но помогите пожалуйста не могу понять некое действие:Условно разместить форму на 4 части .Создать определитель попадания точки в одну из частей.Координаты вводить щелчком мыши. Справился с последним: код procedure TForm1.FormClick(Sender: TObject); var MyMouse: TMouse; begin Form1.Caption := inttostr(MyMouse.CursorPos.x) + 'Х ' + inttostr(MyMouse.CursorPos.y)+'Y'; end; а вот как написать определитель не понимаю.извините что не в тему. Автор, добавлено 4.10.11, 18:06:03 Итак, вы нашли координаты щелчка? Я в дороге, проверить справедливость смогу завтра. Ширина и высота Формы известны. Осталось написать 4 условия, делящие ширину и высоту пополам, и определитель готов. Завтра смогу ответить более предметно. Студент, добавлено 4.10.11, 19:17:37 да,координаты щелчка я нашел,очень жаль что не можете помочь сегодня,завтра работу необходимо сдать,ну ничего буду импровизировать,может и получится. Спасибо за проверку. Автор, добавлено 4.10.11, 19:37:00 If ((cursorpos.x < round(form.width/2)and(cursorpos.y < round(form.height/2)) then showmessage('первый квадрант'); Ну и так далее... Неравенства вроде в 7 классе проходят... Студент, добавлено 4.10.11, 19:55:22 спасибо,понял. Сергей, добавлено 24.01.12, 10:09:13 Хорошая статья! Сергей, добавлено 24.01.12, 10:11:38 А как например можно организовать изменение скорости com порта, если открытие порта происходит в потоке? "Убивать" поток и запускать заново с новой скоростью порта или это можно сделать "внутри" потока? Спасибо. Автор, добавлено 24.01.12, 17:23:04 О, я не в курсе, как вообще работают с com-портом... Не приходилось. Специально изучать не буду, извините... В сети есть инфа по запросу "работа с com-портом delphi". Дмитрий, добавлено 26.01.12, 11:40:20 Спасибо за статью. Все просто и понятно. Однако есть некоторый вопрос. Мне надо в потоке запустить алгоритм, который будет выполняться до тех пор, пока его не остановит оператор нажатием на кнопку остановки. Это может быть 5 минут, а может быть 5 суток. В итоге вопрос следующий: какой командой по нажатию на кнопку "Стоп" я смогу остановить поток? Спасибо. Дмитрий, добавлено 26.01.12, 11:44:02 И еще в дополнение вопрос. Если этот поток будет выполняться в течение 5 суток, надо ли как-то следить за памятью компьютера? Не займет ли поток всю память компьютера за такой долгий промежуток времени? Не повиснет ли комп? Или поток изначально занимает в памяти определенный объем и более его не увеличивает? Автор, добавлено 26.01.12, 21:10:49 Дмитрий, извините за задержку. Остановку работу потока выполняет метод Suspend: MyThread.Suspend; Действия, выполняемые в потоке, приостанавливаются. А что касается памяти, то это зависит не от потока. А от тех действий, которые выполняются в нём. Можно и без потока съесть всю память. А сам по себе, по своему внутреннему устройству, поток не представляет угрозы для памяти или ещё чего-либо. Дмитрий, добавлено 27.01.12, 10:17:01 Спасибо. Ваша статья и ответ очень помогли мне в написании важной программы. P.S. Не ожидается ли статьи по работе с видео? А конкретнее, по отображению видеоизображения с камеры в программе? :) Автор, добавлено 27.01.12, 10:36:48 Дмитрий, хотя это частная тема, и не для начинающих, спасибо да идею. Посмотрю, да и вообще мультимедиа. Дмитрий, добавлено 27.01.12, 11:06:09 К сожалению отправить Вам личное сообщение нельзя, поэтому придется написать здесь. Прошу прощения что не по теме. Я в целом в программировании новичок, однако необходимость заставляет в короткие сроки изучать программирование. Мне необходимо в программе отобразить видео, получаемое с камеры через карту видеозахвата. Вы не могли бы посоветовать источник, где можно найти решение моей проблемы? P.S. Чтобы не захламлять тему сторонними сообщениями, удалите пожалуйста это сообщение после Вашего ответа. Спасибо. ;) Автор, добавлено 28.01.12, 08:49:41 Поискал. Вот здесь есть что-то: delphiexpert.ru/view_download.php?id=131 Пробовал сам ставить указанные компоненты. Влоб не ставятся, нужно подключать мозги, найти недостающие файлы и скопировать в нужные места. Впрочем, там есть комментарии тех, кто это сделал. Дмитрий, добавлено 28.01.12, 19:00:30 Спасибо. С понедельника начну разбираться с видео. Дмитрий, добавлено 30.01.12, 12:48:47 Спасибо вам большое! Скачал образец программы с этим компонентом. Все работает! Теперь буду шаманить, устанавливать этот компонент и встраивать его в программу! Вы помогли мне сделать очень важную для меня программу! трюша, добавлено 5.04.12, 23:29:40 статья оч. помогла!!! Альберт, добавлено 16.05.12, 19:08:20 Доброе время суток. Многоуважаемый автор данного сайта и статьи, у меня к Вам вопрос. Я совсем не давно начал знакомится с циклами и сталкнулся с проблемой паузы в цикле, многие рекомендовали использовать потоки... Дак вот смотрите, простейший цикл, который изменяет свойство Caption объекта TLabel: procedure TMyThread.Execute; var i: integer; begin Synchronize(UpdateCaption); for i:=1 to 20 do begin Label1.Caption := IntToStr(i); sleep(1000); application.ProcessMessages; end; В этом коде компилятор находит ошибку, говорит : [Error] Unit1.pas(47): Undeclared identifier: 'Label1' Такую ошибку выдает при отсутствие компонента на форме.. Но ведь он у меня есть... В чем проблема? Автор, добавлено 16.05.12, 19:29:24 Попробуйте указать полное имя компонента, с указанием формы: Form1.Label1 Альберт, добавлено 16.05.12, 23:03:57 Все получилось. Спасибо огромное... Теперь смогу реализовать свой проект на более высоком уровне... Альберт, добавлено 20.05.12, 20:24:57 Ох надоел наверное уже.. Но вот смотрите, что не так в этом цикле, который находится в потоке.. procedure TMyThread.Execute; Var i,x,y:integer; begin inherited; for i:=1 to n do begin If Form1.Radiobutton1.Checked then begin Mouse_Event(MOUSEEVENTF_LEFTDOWN,x,y,x1,y1); Mouse_Event(MOUSEEVENTF_LEFTUP,x,y,x1,y1); end; sleep(t1); application.ProcessMessages; end; end; Приложение запускается, но когда вызывается данный цикл, то вылезает ошибка: Project1.exe raised excption class EConvertError with message ''' is not a valid integer value'. Process stopped. Use Step or Run to continiue. Что мне делать? Да и это лишь начальная форма цикла, в нем будет много действий(6) с использованием структуры ветвления If Then Else.. Автор, добавлено 20.05.12, 20:38:29 Проверьте значения переменных. x1, y1 либо t1 не являются целыми величинами, а конкретно в данном случае это пустая строка. Именно это означает: '' is not a valid integer value, где '' - строка, причём пустая. Альберт, добавлено 20.06.12, 10:42:59 В том то и дело, что перед тем как запустить цикл с потоком, в кнопке, отвечающей за это, присваивается значение данным переменным...Они идут из поля типа TEdit, поле в свою очередь может содержать лишь числа, буквы и прочие символы туда не впишешь..... Если можно, то дайте мне какие либо Ваши контактные данные, я с Вами свяжусь, для решения данной проблемы.... Автор, добавлено 20.06.12, 10:54:02 Пишите: andrzejx(A)yandex.ru Вася, добавлено 8.04.13, 09:13:27 procedure TMyThread.Execute; begin while True do if Teminated then break; end; тут немного недописано, у меня ругался на строку if Teminated then break; сделал так if MyThread.Teminated then break; наверное стоит поправить статью:) Автор, добавлено 8.04.13, 09:19:21 Да, да, спасибо! Сей момент... Денис, добавлено 23.09.13, 13:08:29 Спасибо за материал!!! |
|