При використанні в додатку декількох потоків необхідно гарантувати, що в даний момент тільки один з потоків може мати доступ до властивостей і методів об'єкта VCL - візуального компонента Delphi, тобто дії потоків необхідно синхронізувати між собою. Для виконання такої синхронізації в Delphi застосовується спеціальний метод Synchronize. в рамках якого і потрібно викликати процедури, що модифікують властивості візуальних компонентів.
Процедура Synchronize використовує в якості параметра ті процедури, в яких відбувається модифікація властивостей візуальних компонентів, і блокує одночасний доступ до компоненту декількох потоків. Ось який приклад, зокрема, міститься в модулі, створеному Майстром створення потоку:
procedure MyThread.Execute;
begin
Synchronize (UpdateCaption);
end;
В даному випадку потік використовується для зміни заголовка Форми. Зміна заголовка відбувається в процедурі UpdateCaption. Здавалося б, для зміни заголовка цю процедуру досить викликати в основний процедурі потоку, Execute. Однак, якщо кілька таких потоків в програмі одночасно спробують змінити заголовок Форми, то це може привести до непередбачуваних наслідків. Для виключення цього процедура UpdateCaption викликається в процедурі Execute як параметр методу Synchronize.
- по-перше, частий виклик Synchronize гальмує виконання програми;
- по-друге, якщо практично всі процедури виконується потоку виконуються з використанням методу Synchronize, то сенсу в створенні такого потоку немає - все одно його робота пройде в головному потоці.
procedure TMyThread.UpdateCaption;
begin
while True do
begin
Form1.Caption: = IntToStr (I); // I - глобальна змінна основної програми, індекс масиву
sleep (100);
end;
end;
procedure TMyThread.Execute;
begin
Synchronize (UpdateCaption);
end;
Бачимо, що відбувається саме те, про що написано вище. Так як весь код потоку, і модифікація заголовка Форми, і цикл очікування, виконується в методі Synchronize. а значить в головному потоці, то додаток буде виглядати завислим, і його навіть буде неможливо коректно завершити.
Тепер спробуємо вивести цикл за межі Synchronize:
procedure TMyThread.UpdateCaption;
begin
Form1.Caption: = IntToStr (Cap);
end;
Це правильний варіант. За допомогою методу Synchronize виконується тільки безпосередня модифікація Заголовку Форми, а цикл очікування виконується в потоці, і не заважає головному потоку.
Деяким об'єктам VCL процедура Synchronize не потрібно, так як вони все ж вміють коректно працювати з потоками, або потребують інших методах синхронізації. Так, коректно працюють з потоками- компоненти доступу до баз даних (з використанням компонентів класу TSession). Виняток становлять бази даних Microsoft Access;
- класи, які працюють безпосередньо з графікою. Це TFont, TPen, TBrush, TBitmap, TMetafile і TIcon. Канву об'єктів цих класів (Canvas) можна використовувати не застосовуючи метод Synchronize. Це робиться за допомогою блокування канви. Тобто, потік, який використовує в даний момент канву, попередньо блокує канву методом Lock, що перешкоджає іншим потокам працювати з канвою, і розблокує потім методом UnLock.