В данной статье приведу простой пример на потоки (Tthread) в Delphi. Рассмотрим основную проблему из-за которой, собственно и создали потоки и посмотрим как её решить в самом простейшем случае. Разместим на форме Progress Bar и кнопку
И на onClick кнопки напишем следующий код
1 2 3 4 5 6 7 8 |
procedure TForm.StartClick(Sender: TObject); var i:integer; begin for i := Form.ProgressBar.Min to Form.ProgressBar.Max do Form.ProgressBar1.Position := i; Sleep(50); end; |
Значения MIN и MAX у Progress Bar выставим в 0 и 1000 000 соответственно. Теперь, если скомпилировать пример и нажать на кнопку Start шкала начнет медленно заполняться.
Проблема
Пока она заполняется – попробуйте передвинуть форму – скорее всего приложение “подвиснет” если не насовсем, то на время заполнения ProgressBar.
А всё почему? Приложение пытается выполнить задачи – последовательно. Мы просим его выполнить некоторую длительную операцию – заполнить шкалу. А ещё мы просим передвинуть окно и оно пытается сделать это всё в один момент. Это как если бы человека попросили одновременно пылесосить, готовить и стирать и ждали бы результата прямо сейчас ))) Понятное дело – тот кто попросил – явно бы расстроился, потому что не получил бы результатов в нужное время. Так и пользователь – не может позволить себе ждать.
Вот это зависание и является проблемой из за которой придумали потоки. То есть, по сути – потоки дают возможность выполнять задачи параллельно. На самом деле, по факту, они выполняются последовательно, но настолько быстро, с такой скоростью переключения, что мы этого не замечаем и для нас они выполняются параллельно. На каждую задачу выделяется квант времени и она двигается по чуть-чуть.
Решение
Перепишем нашу задачу по другому, внедрив класс потоков.
Во-первых внедрим класс потоков
1 2 3 4 |
TFirstThread=class(TThread) protected procedure execute; override; end; |
Во-вторых опишем процедуру execute, которая и является сутью потоков
1 2 3 4 5 6 7 8 9 10 |
procedure TFirstThread.execute; var i:integer; begin inherited; for i := Form.ProgressBar.Min to Form.ProgressBar.Max do Form.ProgressBar.Position:=i; Sleep(50); end; |
В третьих вызовем поток по нажатию кнопки
1 2 3 4 5 6 7 |
procedure TForm.StartClick(Sender: TObject); var i:integer; begin FirstThread := TFirstthread.Create(false);// автозапуск с false FirstThread.FreeOnTerminate:=true; end; |
Всё! Теперь окно можно двигать одновременно с заполнением шкалы
В следующей статье я подробно опишу синхронизацию потоков и метод WaitFor.