ТОР 5 статей: Методические подходы к анализу финансового состояния предприятия Проблема периодизации русской литературы ХХ века. Краткая характеристика второй половины ХХ века Характеристика шлифовальных кругов и ее маркировка Служебные части речи. Предлог. Союз. Частицы КАТЕГОРИИ:
|
Локальные данные потокаКак уже отмечалось ранее одно из основных удобств использования класса TThread, заключается в том, что каждый поток соответствует отдельному экземпляру объекта, и их данные не пересекаться, т.е. каждый поток работает со своими экземплярами переменных класса. Однако, если программист использует для работы с потоками API функции Windows то все потоки будут использовать одни и те же переменные. Для поддержки разделения данных между потоками на уровне функции работы с поттоками в язык Object Pascal введена специальная директива - threadvar, которая отличается от директивы описания переменных var тем, что применяется только к локальным данным потока. Var datal: Integer; threadvar data2: Integer; В приведенном примере переменная datal будет использоваться всеми потоками данного приложения, а переменная data2 будет у каждого потока своя. Подводя итог описания работы с потоками в Delphi, отметим, что в данной среде программирования реализована очень удачная концепция работы с потоками с помощью класса TThread, значительно упрощающая разработку многопоточных приложений. Также у программиста остается возможность работать с потоками с помощью встроенных функций операционной системы, а при необходимости совмещать эти два подхода. Однако не следует совмещать и путать эти два понятия. С точки зрения операционной системы поток - это ее объект, при своем создании он получает дескриптор и отслеживается ОС. Объект класса TThread - это конструкция Delphi, соответствующая потоку ОС. Этот объект VCL создается до реального возникновения потока в системе и уничтожается после его исчезновения.
Упражнение 1. Запустите среду разработки Delphi, откройте новый проект через главное меню File|New|Application либо воспользуйтесь проектом, созданным по умолчанию. 2. Расположите на форме две кнопки с надписями «Start» и «Stop», для задания надписей используйте свойство Caption, для вызова страницы свойств (Object Inspector) используйте клавишу F11 (рис. 1). Рис. 1 3. Создайте для формы обработчик события MouseDown (нажатие кнопки мыши), рисующий на форме круг в текущем положении курсора мыши. Для этого в окне Object Inspector, предварительно выделив форму, выберете закладку Events, на которой найдите событие OnMouseDown. Создайте обработчик события двойным щелчком мыши по полю. Рис. 2 4. В обработчике события введите следующий программный код. procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin Canvas.Pen.Color:=clYellow; Canvas.Brush.Color:=clYellow; Canvas.Ellipse (x - 30, y - 30, x + 30, y + 30); end;
5. Запустите приложение на выполнение, нажав клавишу F9. 6. Добавьте константу с именем Radius и замените ей непосредственное значение радиуса 30. 7. Добавьте программный поток, выполняющий фоновую закраску формы. Для этого выполните команду File|New|Other…, на экране появится окно с шаблонами, в котором следует выбрать элемент Thread Object. Рис. 3 8. Задайте имя создаваемого класса – TPaintThread. Рис. 3 9. В созданном модуле (Unit2) добавьте ссылку на модуль с главной формой (Unit1) и на модуль Graphics. Для этого добавьте ключевое слово uses в разделе implementation. … implementation uses Unit1,Graphics; … 10. В модуле формы (Unit1) добавьте ссылку на модуль с потоком (Unit2), дополнив список уже используемых модулей в разделе uses. 11. Добавьте непосредственно исполняемый код потока в метод Execute класса TPaintThread. procedure TPaintThread.Execute; var X, Y: Integer; begin Randomize; repeat X:= Random (Form1.Button1.Left-10); Y:= Random (Form1.ClientHeight); with Form1.Canvas do begin Lock; Pixels [X, Y]:= clBlue; UnLock; end; until Terminated; end; В данном случае объект Canvas (полотно для рисования на форме) будет являтся разделяемым ресурсом, т.к. к нему одновременно будут обращаться несколько потоков. Объект Canvas формы имеет встроенные средства синхронизации для предотвращения конфликтов при доступе – Lock и UnLock. В общем случае при обращении к форме из разных потоков необходимо использовать метод Synchronize. 12. Добавьте вызов методов Lock и UnLock при обращении к объекту Canvas в главной форме. 13. Объявите переменную для работы с потоком в модуле формы. … var Form1: TForm1; PT: TPaintThread; … 14. Добавьте обработчики события Click кнопок Start и Stop. procedure TForm1.Button1Click(Sender: TObject); begin Button1.Enabled:=False; Button2.Enabled:=True; PT:= TPaintThread.Create(False); end;
procedure TForm1.Button2Click(Sender: TObject); begin PT.Terminate; PT.Free; Button1.Enabled:=True; Button2.Enabled:=False; end; 15. Запустите приложение на выполнение, нажав клавишу F9. 16. При завершении основного потока должны завершиться и все дочерние потоки, для этого в событии FormDestroy нужно завершить и уничтожить поток аналогично тому, как это делается при нажатии на кнопку Stop. 17. Перепишите код обращения к объекту Canvas с использованием метода Synchronize вместо вызовов методов блокировки.
Задание Разработать многопоточное приложение, позволяющие динамически управлять потоками, выводящими на экран круги произвольного радиуса и цвета. Примерная экранная форма представлена на рис. Список «Поток» содержит созданные в программе потоки. Изменение параметров «Приоритет», «Радиус» и «Цвет» применяются к выбранному потоку. Список «Приоритет» позволяет указать приоритет потока.
В поле «Радиус» вводится радиус кругов, рисуемых текущим потоком. При щелчке на поле с цветом выводится стандартное диалоговое окно для выбора цвета потока. При нажатии на кнопку «Создать поток» создается новый поток с параметрами по умолчанию, имя потока добавляется в список потоков. Нажатие кнопки «Завершить поток» уничтожает выбранный в списке поток и удаляет его из этого списка. Список «Приоритет главного потока» позволяет задать приоритет потока формы. Рекомендации Ссылки на созданные потоки удобно хранить в динамическом массиве. Для изменения приоритета главного потока можно использовать приведенные ниже API-функции. MainTh:= GetCurrentThread; SetThreadPriority(MainTh, THREAD_PRIORITY_NORMAL); Не нашли, что искали? Воспользуйтесь поиском:
|