На нашем сайте ежедневно публикуются десятки качественных и свежих материалов, которые Вы можете скачать абсолютно бесплатно. Рекомендуем Вам добавить Наш сайт в закладки, а также подписаться на RSS ленту, чтобы не пропускать интересных новостей.
Напишем приложение, которое будет рисовать в своем главном окне отрезки случайного цвета, размера и расположения. При этом главный поток приложения будет ждать событий от пользователя, а рисованием займется второй поток. Поместите на форму компонент Image и три кнопки Button. В файле исходного кода Unit1 добавьте в секцию интерфейса объявление TDrawThread, реализующего второй поток. В этот класс добавьте приватные атрибуты для хранения координат концов текущего отрезка и его цвета. Из методов класса TDrawThread нам понадобится реализовать, разумеется, Execute, а также новый метод DrawLine, который будет рисовать отрезок в главном потоке. Имя объекта потока добавьте в секцию глобальных переменных после объявления переменной Form1 . Осталось обработать событие формы OnCreate и OnDestroy и события OnClick всех кнопок.
var Form1: TForm1; Thread: TDrawThread; implementation
{$R *.dfm} procedure TDrawThread.Execute; begin repeat X1:=Random(Form1.Image1.Width); Y1:=Random(Form1.Image1.Height); X2:=Random(Form1.Image1.Width); Y2:=Random(Form1.Image1.Height); Color:=TColor(Random($FFFFFF)); Synchronize(DrawLine); until (Terminated = True); end;
procedure TDrawThread.DrawLine; begin Form1.Image1.Canvas.Pen.Color:= Color; Form1.Image1.Canvas.MoveTo(X1, Y1); Form1.Image1.Canvas.LineTo(X2, Y2); end;
procedure TForm1.FormCreate(Sender: TObject); begin Caption:='Пример работы с потоками'; Button1.Caption:='&Начать'; Button2.Caption:='&Остановить'; Button2.Enabled:=False; Button3.Caption:='&Готово'; Thread:=TDrawThread.Create(True); end;
procedure TForm1.FormDestroy(Sender: TObject); begin Thread.Free; end;
procedure TForm1.Button1Click(Sender: TObject); begin Button1.Enabled:=False; Button2.Enabled:=True; Thread.Resume; end;
procedure TForm1.Button2Click(Sender: TObject); begin Thread.Terminate; end;
procedure TForm1.Button3Click(Sender: TObject); begin Application.Terminate; end;
end.
При создании окна приложения создается также обьект для второго потока. Он создается в приостановленном состоянии , потому что запускать этот поток мы собираемся нажатием кнопки «Начать». По нажатии этой кнопки мы вызываем метод Resume глобального объекта Thread, который запускает метод Execute во втором потоке. Рисование отрезков во втором потоке выполняется параллельно с ожиданием действий пользователь в основном потоке, поэтому окно приложения не «зависает»: вы можете перемещать и растягивать окно, а в области рисования продолжится рисование отрезков. Именно поэтому мы сможем рисовать бесконечно, а кнопка «Остановить» все это время будет доступна для нажатия. Второй поток мы хотим завершить аккуратно, поэтому делаем это «кооперативным» способом: нажатие кнопки «Остановить» посылает второму потоку требования завершиться, присваивая атрибуту Thread.Terminated значение True, а метод Execute второго потока проверяет условие Terminated=True на каждой итерации как условие завершения цикла. На каждой итерации цикла генерируются координаты и цвет отрезка и вызывается метод DrawLine, выводящий отрезок в область рисования. Область рисования принадлежит визуальному компоненту, поэтому рисующий код нужно выполнить в основном потоке. Мы добиваемся этого, вызывая DrawLine через метод TThread.Synchronize.