Вопрос

У меня странная проблема с событием Windows Forms.Если быть точным, это КриптонЗаголовокГруппаButtonSpec Click, но это также происходит и с простой ванилью. System.Windows.Forms.Button.

В событии щелчка пользовательский интерфейс отключается (остается метка и кнопка отмены), а затем на основе предыдущего пользовательского ввода создается дорогостоящий запрос LINQ, компилируется и затем выполняется.Есть Application.DoEvents() вызывает foreach, который фактически выполняет запрос (это LINQ для объектов, поэтому он ленив).Это позволяет пользователю нажать кнопку отмены, и после DoEvents, проверяется флаг отмены, и foreach отменяется, и происходит некоторая очистка.Все идет нормально.

Однако когда я нажимаю кнопку «Отмена» после получения первых нескольких результатов (метка показывает, сколько их уже есть), весь обработчик событий Click перезапускается!После добавления некоторых следов кажется, что это происходит до того, как предыдущий обработчик вернется.Другими словами, это происходит в одном из DoEvents звонки.Кнопка, естественно, больше не нажимается.Этого не произойдет, если кнопка отключена в обработчике событий.Но поскольку кнопка не нажата, она не должна снова запускать событие Click, не так ли?

Я озадачен.Очевидно, что обходным путем является отключение кнопки, но я хотел бы знать, в чем может заключаться реальная проблема.Можно ли перезапустить обработчик событий, если DoEvents вызывается до завершения обработчика?Звонит DoEvents не рекомендуется/разрешено в обработчиках событий?Но поскольку в приложении, управляемом событиями, все является обработчиком событий, вы никогда не сможете его вызвать :)

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

  • Первоначально запрос LINQ занимает много времени, прежде чем предоставить первые результаты, т.е.перед первым DoEvents звонок сделан.
  • Запрос LINQ выполняется в потоке графического пользовательского интерфейса, поскольку не имеет смысла разрешать пользователю доступ к остальному приложению, поскольку доступ будет мешать базовому API, используемому как графическим пользовательским интерфейсом, так и запросом LINQ.
  • Я знаю, что мне нужно загрузить запрос LINQ в отдельный домен приложения и выполнить его там, чтобы иметь возможность его выгрузить.Но обычный пользователь будет выполнять лишь несколько разных запросов, а результирующая сборка кэшируется (для одной и той же строки запроса).
  • Проблема больше не возникает, если у меня включена точка останова (вздох - Гейзенберг, кто-нибудь?) или если я отменю встречу позже во время запроса.

Я ценю все, что могло бы объяснить такое поведение, даже если это всего лишь предположения :)

Это было полезно?

Решение

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

Из MSDN: Вызов этого метода может привести к повторному вводу кода, если сообщение вызывает событие.

Долгосрочная перспектива:

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top