«Эмуляция» Application.Run с использованием Application.DoEvents - PullRequest
3 голосов
/ 30 марта 2010

У меня проблемы. Я пытаюсь эмулировать вызов Application.Run с помощью Application.DoEvents ... это звучит плохо, и затем я принимаю также альтернативные решения моего вопроса ...

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

// Create barrier (multiple kernels synchronization)
sKernelBarrier = new KernelBarrier(sKernels.Count);

foreach (RenderKernel k in sKernels) {
    // Create rendering contexts (one for each kernel)
    k.CreateRenderContext();
    // Start render kernel kernels
    k.mThread = new Thread(RenderKernelMain);
    k.mThread.Start(k);
}

while (sKernelBarrier.KernelCount > 0) {
    // Wait untill all kernel loops has finished
    sKernelBarrier.WaitKernelBarrier();
    // Do application events
    Application.DoEvents();
    // Execute shared context services
    foreach (RenderKernelContextService s in sContextServices)
        s.Execute(sSharedContext);

    // Next kernel render loop
    sKernelBarrier.ReleaseKernelBarrier();
}

Этот фрагмент кода выполняется подпрограммой Main. Практически у меня есть список классов ядра, который работает в отдельных потоках, эти потоки обрабатывают форму для рендеринга в OpenGL. Мне нужно синхронизировать все потоки ядра, используя барьер, и это прекрасно работает. Конечно, мне нужно обрабатывать сообщения формы в основном потоке (основной подпрограмме) для каждой созданной формы, и я действительно вызываю Application.DoEvents () для выполнения этой работы.

Теперь мне нужно изменить приведенный выше фрагмент, чтобы он имел общую форму (простое диалоговое окно) без использования 100% ресурсов ЦП, вызывающих Application.DoEvents (), как это делает Application.Run.

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

Как это могло быть возможно?

Примечание: приведенный выше фрагмент кода должен выполняться в процедуре Main, поскольку контекст OpenGL создается в главном потоке. Перемещение фрагмента в отдельном потоке и вызов Application.Run довольно нестабильно и глючит ...

Ответы [ 3 ]

1 голос
/ 30 марта 2010

В вызове Application.DoEvents () в цикле нет ничего принципиально неправильного. Вот что делает Form.ShowDialog (). Он принимает контрмеры, чтобы гарантировать, что пользователь не может попасть в неприятности: он отключает все окна, кроме диалогового окна, поэтому пользователь не может выйти из приложения или запустить диалоговое окно снова.

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

Вам нужно будет уступить процессор, чтобы избежать 100% загрузки процессора. Самый простой способ сделать это - вызвать Thread.Sleep (1). Проверьте мой ответ в этой теме для примера.

1 голос
/ 30 марта 2010

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

Разве вы не можете использовать Application.AddMessageFilter() для реализации того, что вам нужно?

0 голосов
/ 30 марта 2010

Если вы собираетесь построить цикл сообщений, подобный этому, вам следует PInvoke вызвать фактические функции обработки сообщений Win32 (это все, что Application.Run делает за сценой - у него есть внутренний класс UnSafeNativeMethods, который отображает куча их).

Если вам не нужно продолжать обработку между вызовами сообщений - другими словами, если ваш поток безопасен для сна, когда он не активно обрабатывает сообщение, - тогда связывайте WaitMessage от User32. DLL и положить его в цикле, как:

while (WaitMessage())
{
  Application.DoEvents();
}

Если вам нужна дополнительная помощь, дайте мне знать. Сейчас я нахожусь в процессе переустановки VS, или я бы опубликовал пример приложения, показывающего, как выполнить привязку и PInvoke.

...