Вопрос

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

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

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

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

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

    Решение

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

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

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

    Другие советы

    То, что вы увидите с высоты 20 000 футов, - это 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 () , но держитесь подальше от этого.

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

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

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

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

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