Имеет ли смысл иметь два потока GUI для двух независимых форм? - PullRequest
2 голосов
/ 27 августа 2010

На работе у нас очень загруженное приложение Windows Forms.Он работает на сервере с 24 ядрами.

Поскольку модель Windows Forms включает в себя один поток GUI, обрабатывающий насос сообщений, создается впечатление, что богатый и сложный графический интерфейс плохо использует возможности системы.Я ошибаюсь, говоря это?

Так что мои коллеги обсуждали это.Наше приложение включает в себя две более или менее независимых формы.Идея заключается в том, чтобы вспомогательная форма работала в своем собственном выделенном потоке, освобождая основной поток графического интерфейса приложения для обработки только сообщений, отправляемых в основную форму.

Предположительно, это будет выглядеть примерно так:

void CreateAuxiliaryForm()
{
    Action displayForm = () =>
    {
        var f = new AuxiliaryForm();
        f.ShowDialog();
    };

    displayForm.BeginInvoke(displayForm.EndInvoke, null);
}

Теперь, во-первых, я не знаю, безопасно ли это вообще делать.Но я думаю, что, поскольку эти две формы будут независимыми, для каждой из них должно быть нормально иметь собственную нить.Это правда?

Я сказал «более или менее», и это потому, что я не могу сказать, что две формы не взаимодействуют вообще.Но я и мои коллеги решили, что в любом сценарии, в котором основная форма каким-то образом должна взаимодействовать со вспомогательной формой (скажем, обрабатывая событие, вызванное другим), мы просто должны обязательно использовать Invoke / BeginInvoke для отправки любого кода, связанного с GUI, в соответствующую рассылку сообщений.

Что думают люди об этой идее?

Ответы [ 4 ]

4 голосов
/ 27 августа 2010

Обычно: нет.

Существует несколько возможных причин, по которым многопоточность пользовательского интерфейса может помочь:

  • Вы блокируете поток переднего плана на значительное время (скажем,> 5 с) после действия пользователя
  • Вы блокируете заметные промежутки времени (> ~ 300..500 мс), не запущенные пользователем (например, через периодический таймер)
  • У вас действительно дорогие обновления (рендеринг полноэкранных диаграмм), и вы ожидаете, что дюжина этих форм будет активной.

Иначе нет смысла, даже для «интерфейса из ада» с сотнями кнопок и элементов управления.

Единственным требованием к производительности для пользовательского интерфейса является его плавность, то есть пользователь воспринимает пользовательский интерфейс реагирует на свои действия как «мгновенные», что для большинства действий составляет 100,300 мс (в зависимости от частота действия и «размер» ответа).

Минусов много. WinForms построен поверх графического интерфейса Win32, где многопоточность «своего рода работает для форм верхнего уровня», но требует некоторой осторожности, чтобы получить право. Internet Explorer использует даже отдельные процессы , и некоторым надстройкам все еще удается отключить все вкладки при зависании одной страницы.

3 голосов
/ 27 августа 2010

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

Кстати, я предпочитаю, чтобы этот шаблон запускал форму в своем собственном цикле сообщений, хотя ваш метод должен работатьа также:

new Thread(() => Application.Run(new Form1())).Start();
1 голос
/ 27 августа 2010

Я не думаю, что вы можете купить себя, запустив отдельные формы в разных потоках.Взять, к примеру, мой ЭЛТ-монитор.Он обновляется с максимальной скоростью 70 кадров в секунду.Это независимо от того, сколько потоков я посвящаю обновлению пользовательского интерфейса;это просто не может выдвинуть больше кадров в секунду.Ваш средний кинотеатр обновляет экран со скоростью всего 24 кадра в секунду и все еще создает иллюзию непрерывной анимации.

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

1 голос
/ 27 августа 2010

Это должно быть в порядке, если обновления GUI происходят в соответствующих потоках (с помощью Control.Invoke) и любой доступ к общему состоянию осуществляется через потокобезопасный способ.

Кстати, интенсивность ЦП может указывать на некоторую обработку / расчет - возможно, вы можете ввести параллелизм там. Конечно, это может означать много изменений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...