C # - Win Forms - Цикл потока событий

2

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

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

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

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

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

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

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

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

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

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

(3) Какова логика события, которая препятствует возврату события?

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

Теги:
delegates
events

4 ответа

4
Лучший ответ

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

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

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

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

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

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

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

1

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

Этот код:

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);
}

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

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

public event MyDelegate MyEvent
{
    add
    {
        ...
    }

    remove
    {
        ...
    }
}

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

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

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

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

0

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

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

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

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

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

  • На самом деле они делают это за кулисами. Это особенность VB.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню