Как заблокировать пользовательский интерфейс Winforms во время фонового потока - PullRequest
10 голосов
/ 15 марта 2009

Я унаследовал приложение Winforms, которое выполняет много длительных вызовов на сервер приложений из потока пользовательского интерфейса, поэтому пользовательский интерфейс остается неотзывчивым, непригодным к использованию, не подлежащим закрытию в течение достаточно долгого времени. (Что заставляет меня действительно идти AAAAAAAAARGH! )

Я планирую переместить вызовы сервера в фоновый поток и отключить пользовательский интерфейс - но можно перемещать и закрывать - пока фоновый поток выполняет свою работу.

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

Есть ли какой-либо способ в Winforms, чтобы запретить пользователю запускать действия или изменять данные в приложении, пропуская несколько вариантов выбора (изменить размер, показать, скрыть и создать семью, а пользователь закрыть окно)? Я бы предпочел способ, при котором я не получал бы доступ к каждому элементу пользовательского интерфейса в моих формах и устанавливал его как отключенный ... их довольно много, и это приложение действительно "взломано" в конструкторе пользовательского интерфейса, пока оно не показывает кричащие вещи "стиль исходного кода. Нет способа рефакторинга КАЖДОГО вонючего до даты релиза ...

Да, кстати, это приложение живет в .net framework 2

Ответы [ 6 ]

6 голосов
/ 15 марта 2009

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

5 голосов
/ 15 марта 2009

Выберите какой-либо контейнерный элемент управления верхнего уровня (может быть самой формой) и установите для его свойства Enabled значение false. Все элементы управления, размещенные на этом элементе управления, будут отключены, что не позволит им получать ввод.

3 голосов
/ 21 сентября 2011

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

Скажем, у вас есть кнопка поиска и кнопка сброса. Когда вы нажимаете кнопку «Поиск», вы отключаете обе кнопки. Поиск продолжается некоторое время. Если пользователь нажимает «Сброс», даже если он отключен, поиск будет сброшен сразу после завершения.

Быстрый и грязный способ это добавить

Application.DoEvents();

позвоните непосредственно перед повторным включением кнопок. DoEvents () обработает все события щелчка на элементах управления, которые будут игнорироваться для элементов управления, которые все еще отключены.

1 голос
/ 15 марта 2009

На уровне Win32 API есть функция EnableWindow , с помощью которой вы можете отключить любую оконную стрелку (разумеется, вам необходимо получить основной дескриптор вашего главного окна и любых других окон верхнего уровня) , Я не проверял это в WinForms, все же. (Я почти уверен, что есть другие ответы на уровне User32, но я не могу вспомнить вызовы API прямо сейчас.)

Примечание: это не затеняет элементы управления, что снижает их полезность с точки зрения удобства использования (пользователь просто видит «замороженное приложение»). Будет немного лучше, если вы хотя бы установите курсор на песочные часы.

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

0 голосов
/ 25 февраля 2016

Я отвечаю на старую ветку здесь, но я видел этот вопрос и вспомнил свое старое приложение WinForm, где у меня была та же проблема с отключением формы, в то же время позволяя изменять ее размер, перемещать и т. Д. Я загрузил свой код и нашел решение было:

  1. Поместите элемент управления Panel в форму и присвойте свойству Dock значение DockStyle.Fill.
  2. Вместо того, чтобы помещать все составляющие элементы управления верхнего уровня формы непосредственно в форму, поместите их в элемент управления Panel.
  3. Теперь для магического бита - когда вы хотите отключить элементы управления формы, просто установите для свойства Enabled панели значение false. Когда вы сделаете это, все элементы управления, содержащиеся в элементе управления Panel, тоже станут отключенными, но сама форма все еще включена, и, следовательно, изменяет размер и т. Д. Чтобы восстановить состояние всех элементов управления, просто установите для свойства Enabled значение true.

Строго говоря, вам не нужно использовать элемент управления Panel, любой контейнерный элемент управления должен демонстрировать такое же поведение. Даже элемент управления PictureBox сделает свое дело!

0 голосов
/ 15 марта 2009

К сожалению, с WinForms вам, вероятно, потребуется отключить / включить кнопки в одном общем методе. Это одно из преимуществ WPF по сравнению с оконными формами - с этими ситуациями гораздо проще справиться.

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

Вы захотите сделать что-то вроде кнопки отключить ваши элементы управления, вызвать вашу операцию в пуле потоков, а затем снова включить их по завершении.

...