TThread.Synchronize вызывает (почти) тупик в Delphi 2009 (работал в Delphi 7) - PullRequest
3 голосов
/ 12 октября 2011

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

Размещение этого кода:

    procedure TMyForm.FormCreate(Sender : TObject)
       Classes.WakeMainThread := WakeMainThread;
    end;

    procedure TMyForm.WakeMainThread(Sender: TObject);
    begin 
      SendMessage(Application.MainForm.Handle, WM_NULL, 0, 0);
    end;

Ускоряет процессс нормальной скоростью.Но я получаю: EAccessViolation in module rtl120.bpl когда поток умирает, если он используется в модальном приложении (отлично работает для простой диалоговой утилиты).Я предполагаю, что Classes.WakeMainThread () вызывается так же, как и в Delphi 7, но отправка WM_NULL в application.handle ничего не выполняет.Я думаю, пришло время «получить степпин».

Ответы [ 2 ]

6 голосов
/ 13 октября 2011

Внутренние элементы механизма Synchronize() не сильно изменились между D7 и D2009.Конечно, были добавлены новые функции (асинхронная организация очереди, анонимные методы и т. Д.), Но основная реализация кода для запуска в основном потоке не изменилась.Скорее всего, что-то еще в коде основного потока, которое вы еще не показали, блокирует основной поток от обработки ожидающих сообщений и Synchronize() запросов правильно.

4 голосов
/ 10 января 2012

TApplication.Create вызывается из другой DLL, следовательно, он пробуждает неверный дескриптор или какую-то ерунду в этом обратном вызове.

Вам необходимо исключить статически связанные библиотеки DLL, которые включают [vcl.] Controls.pas, потому что TApplication.Create происходит в некотором коде инициализации в этом модуле.

Как только вы сделаете это, синхронизация будет восстановлена ​​в своем былом великолепии.

К сожалению, исправления, которые вы делаете в одной версии Delphi, могут быть отменены из-за изменений, внесенных в другой версии Delphi.Так что, если проблема вернется, вернитесь к чертежной доске.Пройдите через код инициализации, в частности, процедуру initUnits в system.pas.Он запускает код инициализации и в конечном итоге наталкивается на vcl.controls.pas, и вы можете заглянуть в запись UnitInfo, чтобы выяснить, из какого файла вызывается этот файл.


Лучший способ исправить это - использовать delayed со всеми внешними dll (по крайней мере со всеми внешними DLL-библиотеками Delphi VCL).

 function didntknowIusedcontrolsbutIdo() : Integer; external 'useful.dll' delayed;

Но это толькоработает в Delphi 2010 и выше.Хорошо, что вы перешли на XE2 между моментом, когда вы задали этот вопрос, и временем, когда вы наконец нашли удовлетворительный ответ на него.

...