Могу ли я переместить Delphi TThread.Synchronize() локально в форму VCL, которая будет вызываться из основного или рабочего потока?
Я использую CreateAnonymousThread для рабочей задачи, и когда я начал с ней, я использовал Synchronize во всей декларации в соответствии с документированными примерами, например:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here before worker stuff
NotifyBeforeWorkerStuff;
end);
// Do worker stuff
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
// Here after worker stuff
NotifyAfterWorkerStuff;
end);
end);
FExecutionThread.Start;
end;
end;
Как вы видите, из этого потока я запускаю уведомления о событиях для различных частей моего приложения, включая формы VCL (NotifyBeforeWorkerStuff и т. Д.). Позже я увидел, что мог бы перемещать Synchronize() более локально к каждой форме VCL близко к точке, которая фактически требовала ее для обновления (небезопасных) элементов управления VCL:
procedure TSomeVCLForm.ReceiveNotification;
begin
TThread.Synchronize (TThread.CurrentThread,
procedure ()
begin
Label1.Caption := GetSomeStringFunction;
end);
end;
Рабочий поток становится проще, если я живу с уведомлениями из основного или рабочего потоков:
procedure Txxx.RunWorker;
begin
FExecutionThread := TThread.CreateAnonymousThread(procedure ()
begin
NotifyBeforeWorkerStuff;
// Do worker stuff
NotifyAfterWorkerStuff;
end);
FExecutionThread.Start;
end;
У меня есть несколько вопросов о том, правильно ли это:
- Мои уведомления могут быть из рабочего потока, но также из основного потока (например, полученные из нажатия кнопки). Итак, когда "ReceiveNotification" в форме VCL вызывается из основного потока, разрешается ли вызывать TThread.Synchronize, как указано выше? Документы XE8 не подразумевают, но проверяют System.Classes, это выглядит нормально и работает нормально.
- Внутри "ReceiveNotification", когда Label1.Caption выбирает строку из GetSomeStringFunction, верно ли, что нет абсолютно никакой необходимости в блокировке внутри этой функции, даже если вызов выполняется из рабочего потока?
Спасибо за любой совет.
1 ответ
В документации сказано:
Предупреждение: не вызывайте Synchronize из основного потока. Это может вызвать бесконечный цикл.
Я думаю, что документация просто неверна. Реализация в XE8 проверяет, является ли текущий поток основным потоком. Если это так, то метод выполняется напрямую.
Блокировка не требуется в ReceiveNotification
потому что призыв к GetSomeStringFunction
всегда выполняется в главном потоке.