2009-03-15 2 views
10

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

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

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

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

О, кстати, это приложение живет в рамках .net 2

+0

Почему вы просто отключили кнопку, которая инициировала длительный вызов? –

+0

Пользовательский интерфейс - это форма ввода данных, длительный вызов может быть «сохраненным», включающим множество объектов домена. Я хочу, чтобы пользователь не изменял данные в форме, пока, к примеру, выполняется сохранение. Кстати, ЭТО (http://stuffthathappens.com/blog/2008/03/05/simplicity) является истинным ... – froh42

+0

, когда вы хотите включить обратно форму? если вы попытаетесь сделать это в событии «_RunWorkerCompleted», вы получите исключение, потому что вам не разрешено (http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx - первое примечание). Вы можете делать это вручную только для каждого элемента в форме или для первого контейнера. – Edd

ответ

6

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

+0

невозможно: операция поперечного потока недействительна: элемент управления 'groupBox2' доступен из потока, отличного от потока, на котором он был создан. :( – Edd

+1

@Edd Вам нужно отключить пользовательский интерфейс из потока пользовательского интерфейса, а не фоновый поток. Тогда он будет работать. – Andy

+0

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

5

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

0

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

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

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

1

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

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

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

3

Проблема простое включение/выключение кнопки в том, что события UI все еще добавляются к MessageQueue во время выполнения задания ....

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

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

Application.DoEvents(); 

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

+0

О, это * ужасно *. Я использую это. – Frosty840

0

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

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

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

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