2009-11-13 3 views
1

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

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

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

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

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

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

/Brian

+1

«Но, как я вижу, вы можете создавать новый процесс только при выполнении новой программы». -> Это правда. Ни в коем случае вы не можете сделать эту работу по назначению. Переверните свою логику и поместите свою операцию в поток. – Mihaela

+0

См. Статью Эмбаркадеро [Создание рабочей темы для обработки фоновых изображений] (http://edn.embarcadero.com/article/25707). – naXa

ответ

9

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

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

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

+1

@mghie: Я думаю, вы пропустили тот факт, что тяжелая работа выполняется в основном потоке, а вторичный поток должен обновлять прогресс. Это обратная логика, ИМО. –

+0

@Ken: Это то, что я пытался сказать в третьем абзаце. Может быть, я должен это прояснить? – mghie

+0

@ mghie: Nah. Когда я перечитаю его, я думаю, что я сделал большой акцент на том, что вы сказали в первом абзаце, и не уделял достаточного внимания последнему. Выглядит хорошо. –

7

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

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

+0

Вторая часть неверна, так как другие потоки, по крайней мере, одинакового приоритета, безусловно, получат возможность работать. Кроме того, визуальные элементы управления Windows являются потокобезопасными, поскольку взаимодействие происходит через сообщения, которые сериализуются через очередь сообщений. – mghie

+0

Не так много, если основной поток вовлечен в «тяжелую работу» и не дает (спать). Вот почему логика отстала; основной поток приложения делает его передним потоком, и этот поток почти всегда получает повышение приоритета (если вы не настроили свою систему специально для работы в качестве сервера и не отдавали приоритет фоновым потокам). Думаю, я должен был сказать «достаточно», а не «не буду». Я исправлю это сейчас. –

+0

Я согласен, что повышение приоритета влияния может иметь. Однако, если система имеет более одного ядра (это может быть разумным предположением сегодня. Я, как правило, думаю в основном в терминах нескольких ядер сейчас :-) и не полностью голоден от циклов процессора, он должен дать обеим потокам их долю ЦПУ. Но 'Синхронизация' - блестящее оружие для рендеринга дополнительных ядер бесполезно. – mghie

0

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