Подтвердить что ты не робот

Опасно ли использовать синхронизацию в приложении, отличном от VCL?

Если код Delphi был написан с синхронизацией для сериализации доступа к основному потоку VCL, но этот код затем используется в приложении, отличном от VCL, будет ли он синхронизироваться с основным потоком приложения или просто не имеет никакого эффекта вообще?


Пример:

procedure TMyThread.Execute;
begin

  // ... other code

  Synchronize(SomeMethod);

  // ...

end;

Предположим, что

  • это приложение, отличное от VCL, которое имеет основной поток, который выполняется в бесконечном цикле (или до его завершения)
  • основной поток не вызывает CheckSynchronize напрямую или в обработчике WakeMainThread
  • выполняется вторичный поток и выполняет синхронизацию (SomeMethod), как в приведенном выше примере

Будет ли винт зависать на линии Synchronize (SomeMethod)?

4b9b3361

Ответ 1

TThread предоставляет средства для программ, отличных от VCL, для проверки очереди синхронизации, поэтому они могут продолжать использовать многопоточные библиотеки, которые ожидают синхронизации своих методов. Это описано в документации для CheckSynchronize. Помните, что это задание приложения для проверки очереди, а не вашей библиотеки.

Пока приложение выполняет свою часть контракта, ваше использование Synchronize должно быть прекрасным. Если это не так, то ваша программа будет работать некорректно, но я не знаю, какие именно симптомы следует ожидать. Висячие, безусловно, звучат правдоподобно.

Ответ 2

Возможно ли использовать синхронизацию в приложении, отличном от VCL?

Да, это опасно. Если ваш основной поток не вызывает CheckSynchronize, тогда Synchronize приведет к тупиковой ситуации.

Предположим, что

  • это приложение, отличное от VCL, которое имеет основной поток, который выполняется в бесконечном цикле (или до его завершения)
  • основной поток не вызывает CheckSynchronize напрямую или в обработчике WakeMainThread
  • выполняется вторичный поток и выполняется Synchronize(SomeMethod), как в приведенном выше примере

Будет ли винт зависать на линии Synchronize(SomeMethod)?

Вызов Synchronize блокирует фоновый поток, пока основной поток не вызовет CheckSynchronize. Итак, если основной поток никогда не вызывает CheckSynchronize, фоновый поток будет блокироваться бесконечно.

Следующая программа иллюстрирует это:

program TheBigSleep;

{$APPTYPE CONSOLE}

uses
  SysUtils, Classes, Windows;

type
  TMyThread = class(TThread)
  protected
    procedure Execute; override;
  end;

procedure TMyThread.Execute;
begin
  Synchronize(SysUtils.Beep);
end;

begin
  with TMyThread.Create do
    WaitForSingleObject(Handle, INFINITE);
    //don't call WaitFor since that, in turn, calls CheckSynchronize
end.

Ответ 3

Поскольку вы помещаете код Delphi в библиотеку для использования другими приложениями, я бы не советовал использовать Synchronize() вообще, так как в потоке нет понятия о том, что происходит вне себя. Лучший выбор заключается в том, чтобы поток показывал событие обратного вызова, которое поток может вызывать в своем собственном контексте, когда это необходимо, а затем позволяет приложению предоставлять обработчик функции обратного вызова, который решает наилучший способ синхронизации с основным потоком приложения при необходимости.