2009-12-05 3 views
0

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

+0

Я просто добавляю заметку, чтобы вы могли видеть, что я обновил свой ответ в ответ на ваш вопрос. – David

ответ

2

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

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

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

Application.DoEvents()

внутри цикла. Это позволит приложению проявлять отзывчивость, если цикл работает, когда он обычно просто заперт.

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

foreach(DataRow r in myTable.Rows) 
{ 
    StatusLabel.Text = "Now processing " + r[0].ToString(); 
    Application.DoEvents(); 
    ... now do the real work 
} 

Это дает пользователю обратную связь, чтобы позволить им знаете, что приложение действительно что-то делает, а не просто «Заблокировано». 99% времени, восприятие пользователя - все, что имеет значение.

Редактировать - добавил ответить комментарий ниже

Application.DoEvents() делает включают удар по производительности. Вам нужно решить, стоит ли это. Используемый, как я показал выше (в сочетании с индикатором прогресса какой-то), он может устранить разочарование пользователя, и я нашел его полезным компромиссом для длительных процессов.

В моем первоначальном ответе было сказано, что восприятие - это все, что имеет значение 99% времени. Я приведу пример того, где я его использовал, и почувствовал, что это оправдано.

Я унаследовал приложение WinForms, написанное одним из моих предшественников. У этого приложения был процесс, который нужно было делать еженедельно, чтобы суммировать и обрабатывать миллионы записей. Помимо большого количества записей, база данных не была спроектирована должным образом, и в результате процесс занял более часа. Таким образом, пользователь застрял бы на своем компьютере в течение часа, наблюдая, как этот экран ничего не делает. У них не было возможности узнать, действительно ли приложение работает. Я добавил код выше как временную меру, и конечный пользователь был чрезвычайно благодарен. Он действительно оценил, что приложение действительно работает, а не просто повесило трубку.

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

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

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

+0

Большое вам спасибо за ваш совет. У меня есть один вопрос. я получил довольно острый спор над Application.DoEvents некоторое время назад. В принципе, человек сказал мне не использовать его, поскольку он использует больше памяти или что-то еще, и даже дал мне ссылку на сайт, который заявляет Application.DoEvents() как зло. Это правда? –

+0

Большое спасибо Дэвиду, это было очень полезно, и я ценю время, которое вы приняли, чтобы ответить на мои вопросы: D
Думаю, я мог бы сейчас взглянуть на материал Async IO, может быть, это будет трюк. Я буду использовать Applciation.DoEvents(), в то время как я прочитал этот асинхронный материал. Можете ли вы поверить, что я еще не узнал ни одного асинхронного материала? –

1

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

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

+0

Благодарим вас за ответ. Очень полезно. –

2

Вы должны попытаться заставить приложение не перестать отвечать на запросы.

Один из способов сделать это - запустить эти сложные задачи в разных потоках и после таймаута kill'em.

+0

Kill'em ... при необходимости. –

+0

да, конечно :) –

+0

+1. для первого предложения. – David

0

Я бы сделал это так: периодически включайте таймер в основной поток, сбрасывая счетчик на 0. Затем в другом потоке есть еще один таймер, который увеличивает счетчик. Когда счетчик достиг определенного значения, это означает, что основной поток перестает отвечать на какое-то время.