Как избежать замерзания нити, когда основное приложение занято - PullRequest
1 голос
/ 13 ноября 2009

У меня небольшая проблема. Я хочу отобразить форму прогресса, которая просто показывает анимацию, когда основное приложение выполняет тяжелые операции.

Я сделал это в потоке, и он отлично работает, когда пользователь не выполняет никаких операций. Но он просто останавливается, когда мое основное приложение занято.

Я не могу поместить Application.ProcessMessages между различными строками кода, потому что я использую компоненты третьей стороны с большим временем обработки.

Моя идея состояла в том, чтобы создать новый процесс и в процессе создать поток, который выполняет анимацию. Теперь это не остановит выполнение потоковой формы, когда основное приложение выполняет тяжелые операции.

Но, как я понимаю, вы можете создать новый процесс, только если вы запускаете новую программу.

Есть ли у кого-нибудь решение о том, как заставить поток продолжить выполнение, даже когда основное приложение занято?

/ Brian

Ответы [ 3 ]

9 голосов
/ 13 ноября 2009

Если ваш рабочий поток не имеет более низкого приоритета, чем основной поток, вы не используете метод Synchronize(), не вызываете SendMessage() и не пытаетесь получить какой-либо объект синхронизации, который является основным графическим интерфейсом пользователя. поток уже получен, тогда ваш вторичный поток должен продолжать работать.

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

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

7 голосов
/ 13 ноября 2009

Ваша логика обратная. Ваша ветка должна выполнять «тяжелую работу» и передавать сообщения в основное приложение для обновления прогресса или анимации.

Если вы оставите всю «тяжелую работу» в своем основном приложении, другой поток не получит достаточно шансов на выполнение, а значит, у него не будет возможности что-либо обновить. Кроме того, весь доступ к GUI (элементам управления VCL) должен происходить в главном потоке приложения; VCL не является потокобезопасным. (Как и сама система Windows, когда речь идет о визуальном контроле.)

0 голосов
/ 13 ноября 2009

Если от "Есть ли у кого-нибудь решение о том, как заставить поток продолжить выполнение, даже когда основное приложение занято?" вы имеете в виду, что основной поток занят, вы должны переместить код, который потребляет основной поток, в другой другой поток. Другими словами, главный поток должен отвечать за запуск и остановку действий, а не за их выполнение. Disclaymer: На самом деле я не знаю Delphy, но я думаю / надеюсь, что концепции очень похожи на C ++ или C #.

...