2010-03-11 4 views
0

Есть ли (или у вас есть собственный) предпочтительный способ обработки фонового изображения в срезах в потоке пользовательского интерфейса в Windows Forms? Как OnIdle() в MFC?Фоновая обработка на потоке пользовательского интерфейса? (Winforms)

В собственном программном обеспечении Windows вы можете использовать свой собственный цикл сообщений, но Application.Run() не дает нам доступ к контуру сообщения.

Событие Application.Idle не дает возможности запускать его повторно.

Я думаю, вы могли бы вызвать native PostMessage() с помощью P/Invoke (так как нет управляемой версии), чтобы опубликовать личное сообщение «WM_IDLE» и переопределить WndProc(), чтобы поймать его. Я не знаю, как это будет с Application.Run().

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

ответ

1

Лучший вариант, который я видел, - использовать модифицированную версию Managed DirectX Render Loop designed by Tom Miller. Добавив вызов в Thread.Sleep() внутри цикла рендеринга, вы можете резко снизить потребление ЦП.

Для этого требуется вызов P/Invoke для отслеживания того, что приложение все еще находится в режиме ожидания, но до тех пор, пока он неактивен, вы можете сделать «таймер», который непрерывно срабатывает во время фаз бездействия, и использовать это для выполнения вашей обработки ,

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

+0

1. AFAIK Многие из моих пользователей не имеют «современных систем» по этому определению. 2. Пользовательский интерфейс быстро использует новые данные, генерируемые фоновым процессом, следовательно, все обычные проблемы многопоточности. 3. 99% работы выполняется в фоновом режиме, поэтому отдельные ядра для пользовательского интерфейса и фона не будут покупать гораздо большую общую пропускную способность. –

+0

@Conrad: Почему я действительно дал вам вариант, который полностью остается в потоке пользовательского интерфейса ... Однако даже «низкие» системы за последние 3-5 лет обычно имеют 2 ядра. Помещение всей вашей обработки на фоновый поток позволяет поддерживать активный пользовательский интерфейс даже в одноядерной системе с низким уровнем доступа и, вероятно, проще, чем пытаться выполнять плановую обработку во время простоя. Это, как говорится, подход выше работает очень хорошо ... –

+0

@Conrad: Я только что понял - у меня была неправильная ссылка! Тот, который я поставил выше, должен иметь больше смысла ... Он использует Application.Idle с AppStileIdle в цикле - позволяет вам делать то, что вы хотели. (Извините за это - я вставил неверный ранее). –

0

Я думал о своем собственном возможном ответе, вдохновленном разговорами Рида о многопоточности. У меня может быть способ перезапуска приложения Application.Idle:

Создайте скрытую форму, назовем ее формойRetrigger.

В Application.Idle запустите мой метод Retrigger() в потоке пула потоков.

Retrigger() вызывает формуRetrigger.InvokeOnClick() (или любые другие методы «Control.Invoke»). Я ожидаю, что это запустит другое сообщение через очередь приложения, заставив Idle снова запускаться.

Смежные вопросы