C # - Win Forms - Цикл потока событий - PullRequest
2 голосов
/ 22 августа 2009

Я читал рефкарту Джона Скита на C #. Он заявил:

«События тесно связаны с делегатами, но это не одно и то же».

Итак, насколько я понимаю, когда возникают события, обработчики (делегаты) выполняют код.

У меня есть следующие сомнения:

(1) Когда мы объявляем событие, оно будет зарегистрировано в каком-либо «РЕГИСТРАЦИЯХ»? или "Системные реестры"?

(2) Старый стиль VB 6.0 обрабатывает событие без делегатов, так почему мы не можем написать событие без делегатов?

Как работает поток для Win Forms: Если я нажму кнопку, она напечатает привет (следующий пример).

button_click( sender,some event args  )
{
    print();
} 

void print( )
{
    console.WriteLine ("Hello");
}

Как этот поток событий внутренне связан и обрабатывается? (Что внутри происходит в CLR?)

(3) Какая логика стоит за событием, которое не дает событию вернуть значение?

Спасибо всем, что потратили свое золотое время.

Ответы [ 4 ]

4 голосов
/ 22 августа 2009

A delegate - определение типа. Он указывает сигнатуру, что метод должен быть совместимым.

event является элементом класса, подобным свойству, на основе типа делегата. Он обеспечивает инкапсуляцию, единственные открытые действия - добавить (+ =) или удалить (- =) обработчик.

(1) Нет, событие нигде не зарегистрировано. Но это место, где регистрируются методы обработки.

(2) Я не знаю, как работает VB6, но в .NET все события основаны на делегатах.

(2b) При нажатии кнопки происходит то, что код кнопки проверяет, не является ли событие нулевым, и затем вызывает событие (как метод). Событие перебирает свой список вызовов и вызывает все зарегистрированные обработчики.

есть еще кое-что: ButtonClick создается самой Button, когда она обрабатывает и обрабатывает события мыши и / или клавиатуры. Эти события приходят из MessageLoop (Application.Run). Но на уровне CLR это просто означает, что MessageLoop вызывает метод (Control.Perform (..)) для Button.

(3) Вы можете написать делегат и / или событие, которое просто отлично возвращает значение. Но подумайте, что это значит, когда есть несколько обработчиков. Подпись void handler(object sender, Eventargs e) является (сильной) рекомендацией.

1 голос
/ 22 августа 2009

События реализованы с использованием делегатов:

Этот код:

public event EventHandler<YourEventArgs> YourEvent;

Будет скомпилировано во что-то вроде этого:

// a private field
private EventHandler<YourEventArgs> YourEvent = null;

// public add_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_YourEvent(EventHandler<YourEventArgs> value)
{
    YourEvent = (EventHandler<YourEventArgs>)
    Delegate.Combine(YourEvent, value);
}

// public remove_ method
[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_YourEvent(EventHandler<YourEventArgs> value)
{
    YourEvent = (EventHandler<YourEventArgs>)
    Delegate.Remove(YourEvent, value);
}

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

Этот код объясняет, почему события могут быть объявлены с использованием следующего синтаксиса:

public event MyDelegate MyEvent
{
    add
    {
        ...
    }

    remove
    {
        ...
    }
}

1) Событие не будет зарегистрировано ни в одном реестре. Память для события (для частного поля делегата) будет выделена в куче, поскольку делегаты являются ссылочными типами.

2) События создаются поверх делегатов, поэтому их нельзя использовать без делегатов.

3) На третий вопрос уже ответил Хенк Холтерман (+1) и другие люди.

Надеюсь, это поможет.

0 голосов
/ 22 августа 2009

1) Нет, обработчики событий будут просто зарегистрированы в Event (который содержит список обработчиков).

2) Я не особо разбираюсь в VB6, но я вполне уверен, что у него была похожая механика, поскольку, по сути, Delegate - просто указатель на метод строгого типа.

В вашем примере событие Button.Click содержит ссылку на делегат button_click( sender,some event args), который он вызывает при инициировании события. Он не содержит ссылки на печать, только ссылку на метод, который должен вызвать.

3) Поскольку для одного события может быть несколько обработчиков (или их вообще нет), возвращаемое значение часто может быть нелогичным. Таким образом, большинство обработчиков событий имеют возврат void. При этом вы можете создавать собственные события, которые могут иметь любую подпись. Подпись void (object sender, EventArgs e) является базовой подписью для большинства, если не всех, событий Microsoft.

0 голосов
/ 22 августа 2009
  1. Я не знаю об этом ... но моя первая мысль о куче, так как именно там большинство объектов живут, а события являются частью объекта ... но я рискну догадаться один ....

  2. Они действительно делают, но за кадром для вас. Это особенность VB.

  3. Они могут иметь более одного делегата / слушателя, и порядок запуска слушателей не гарантируется. Соглашение состоит в том, чтобы использовать объект eventarg для возврата информации обработчику. Почему у событий нет возвращаемых типов в .NET? будет немного лучше описан по этому вопросу.

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