У меня странная проблема с событием Windows Forms. Точнее, это событие ButtonSpec Click , но это также происходит с простой ванилью System.Windows.Forms.Button
.Windows Forms Повторное событие Click
В событии клика пользовательский интерфейс сбрасывается (слева и слева от кнопки «Отмена»), а затем дорогой запрос LINQ строится из предыдущего пользовательского ввода, скомпилирован и затем исполняется. Есть Application.DoEvents()
вызовов в foreach, который фактически выполняет запрос (это LINQ для объектов, поэтому он ленив). Это позволяет пользователю отменить отмену, а после DoEvents
проверяется флажок отмены, а foreach отменяется, и происходит некоторая очистка. Все идет нормально.
Однако, когда я нажимаю кнопку «Отмена» после появления первых нескольких результатов (метка показывает, сколько их уже существует), весь обработчик событий Click перезапускается! После добавления некоторых трасс, кажется, что это происходит , прежде чем предыдущий обработчик вернется. Другими словами, это происходит в одном из вызовов DoEvents
. Кнопка, конечно, не нажата снова. Этого не происходит, если кнопка отключена в обработчике событий. Но поскольку кнопка не нажата, она не должна запускать событие Click, если это так?
Я сбит с толку. Очевидно, что обходным путем является отключение кнопки, но я хотел бы знать, что может быть настоящей проблемой здесь. Можно ли перезапустить обработчик событий, если вызывается DoEvents
до завершения обработки обработчика? Является ли вызов DoEvents
не рекомендованным/разрешенным в обработчиках событий? Но, так как все это обработчик события в приложении событийного, вы никогда не мог назвать это :)
Дополнительные подсказки, которые могут потребоваться для ответа на этот вопрос:
- Запрос LINQ берет длинный прежде чем подавать первые результаты, т.е. до первого вызова
DoEvents
. - Запрос LINQ выполняется в потоке графического интерфейса пользователя, поскольку не имеет смысла разрешать пользователю доступ к остальному приложению, поскольку доступ будет мешать базовому API как GUI, так и запросу LINQ.
- Я знаю, что я должен загрузить запрос LINQ в отдельный домен приложения и выполнить его там, чтобы иметь возможность его выгружать. Но типичный пользователь будет иметь несколько запросов, и собранная сборка будет кэширована (для той же строки запроса).
- Проблема не возникает, если у меня либо есть точка останова включена (sigh - Гейзенберг, кто-нибудь?), Или если я отмене позже во время запроса.
Я ценю все, что бы объяснить поведение, даже если это просто спекуляция :)
Проблема с DoEvents заключается в том, что в этом случае он снова запускает событие, которое произошло только один раз. Второе нажатие на кнопку не было. Я согласен с основной темой в целом, однако я не делал этого в этом приложении, так как базовый API, который используется в запросе, и приложение не являются потокобезопасными, и он доступен из потока графического интерфейса в любом случае в главном часть приложения. Я думаю, что все равно попробую сделать это в отдельном потоке, если скорее для возможности автоматического запроса запроса при закрытии главного окна. – OregonGhost
Хорошо, что это нехорошо, но вы должны делать то, что вам нужно. Другое, хотя: Вы уверены, что не подписались на мероприятие дважды? В противном случае, как насчет библиотеки Криптона, как использовать рефлектор, чтобы увидеть, что он делает? –
Как я уже сказал, это происходит и с простой кнопкой SWF, и я определенно подписался один раз. Если я повторно нажимаю кнопку «Отмена», она будет повторно перезапускать обработчик событий, но все они будут завершены после того, как они пройдут один раз (они выполнены полностью вложенными). – OregonGhost