Асинхронность и .NET события? - PullRequest
       12

Асинхронность и .NET события?

5 голосов
/ 26 октября 2009

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

Как работают события .NET с высоты 20 000 футов? Я не имею в виду шаблон обработчика делегата / события и все это. Что я имею в виду - что такое БОЛЬШАЯ картинка:

  1. Код А что-то делает.
  2. Произошел некоторый внешний триггер. Скажем, например, что пользователь нажал на какой-то элемент управления.
  3. происходит волшебство и вызывается обработчик события.
  4. другое волшебство происходит после того, как обработчик события возвращается.

Теперь, что такое магия? Как это относится к темам? Поток, выполняющий мой код, прерывается при возникновении события, а затем возобновляется после возврата обработчика события? Но я погуглил и обнаружил , что обработчики .NET вызываются синхронно в исходном потоке. Так кто же позаботится о том, чтобы остановить и возобновить код А? Что происходит, если события вложены (то есть событие 2 происходит, когда выполняется обработчик события для события 1)?

Редактировать : Насколько я понимаю, в ответах говорится, что механизм события для события next будет запущен только после завершения текущего работающего обработчика события. Это означает, что ваш код не прерывается: строка n всегда будет выполняться сразу после строки n-1 и непосредственно перед строкой n + 1. Однако непосредственно перед тем, как опубликовать вопрос, я отлаживал программу, управляющую с помощью автоматизации Internet Explorer (используя SWExplorerAutomation от Webius). Я совершенно уверен, что, когда я проходил по коду, я был «похищен» :-) некоторым обработчиком событий и вернулся в прерванную позицию в коде, как только этот обработчик завершил свою работу. Это означает, что либо вы не понимаете ответы, либо программа ведет себя по-разному, проходя через отладчик!

Ответы [ 3 ]

3 голосов
/ 26 октября 2009

Позвольте мне пролить свет на вашу проблему. Волшебство - цикл сообщений Windows. Вы видите в своем примере, на самом деле, ничто не заставляет Code A останавливаться, когда происходит событие. Скорее, это последовательность.

Когда работает код А, пользователь нажимает кнопку. Сообщение окна кнопки ставится в очередь, но ничего не происходит. Когда код А выходит из своей функции или возвращает управление обратно в цикл сообщений, обрабатывается событие Click и запускается обработчик событий.

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

2 голосов
/ 26 октября 2009

То, что вы увидите на расстоянии 10000 футов *, это MessageLoop . Он внутри Application.Run().

Проще говоря, это цикл while, который запускает весь жизненный цикл вашего приложения и выполняет

  // pseudo code, I did not reflector Application.Run
  while (GetMessage(ref msg)
  {
     DispatchMessage(ref msg);
  }

Вы заметите simgle-thread, когда будете слишком долго обрабатывать событие 1, ваше приложение будет помечено как «не отвечающее» в TaskManager.

Связанный метод - Application.DoEvents(), но держитесь подальше от этого.

1 голос
/ 26 октября 2009

События - это указатели на функции (как мы привыкли иметь в C ++). Когда вы используете обычное ванильное событие .NET, вы на самом деле вызываете функции, которые подключаются с помощью + = к этому событию. Итак, с высоты 20 000 футов ваш код на самом деле вызывает какой-то другой код, точно так же, как и вызов другой функции. Вот почему он вызывается синхронно и в одном и том же потоке.

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

Основной поток элементов управления опрашивает новые сообщения, и когда появляется новое сообщение, он выполняет его (снова в основном потоке), только теперь оно не совсем синхронно.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...