Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Когда класс определяет множество событий с помощью объявлений событий, таких как поле, компилятор создает резервное поле для каждого из них. Каждый экземпляр этого класса выделяет память для всех этих полей, даже для событий, обработка которых никогда не выполняется. При наличии множества событий избыточные затраты на экземпляр приводят к неэффективному использованию памяти.
Чтобы избежать этой нагрузки на память, используйте свойства событий, поддерживаемые коллекцией делегатов. Коллекция должна предоставлять методы, которые устанавливают, обеспечивают доступ и извлекают делегатов по ключу события. EventHandlerList предназначен для этой цели, но вы также можете использовать класс, производный Hashtable от DictionaryBase. Сделайте детали реализации коллекции скрытыми.
Каждое свойство события определяет методы доступа для добавления и удаления. Метод доступа add добавляет делегат ввода в коллекцию делегатов, а метод доступа remove удаляет его. Оба метода доступа используют предопределенный ключ для добавления и удаления экземпляров из коллекции.
Необходимые условия
Ознакомьтесь с понятиями в статье "События ".
Определение нескольких событий с помощью свойств события
Эти шаги создают Sensor класс, предоставляющий 10 свойств событий, которые поддерживаются одним EventHandlerList.
Определение класса данных событий, наследуемого от EventArgs.
Добавьте свойства для каждого фрагмента данных, которые необходимо передать обработчику:
public class SensorEventArgs(string sensorId, double value) : EventArgs { public string SensorId { get; } = sensorId; public double Value { get; } = value; }Public Class SensorEventArgs Inherits EventArgs Public ReadOnly Property SensorId As String Public ReadOnly Property Value As Double Public Sub New(sensorId As String, value As Double) Me.SensorId = sensorId Me.Value = value End Sub End ClassОбъявите EventHandlerList поле для хранения делегатов:
protected EventHandlerList listEventDelegates = new();Protected listEventDelegates As New EventHandlerList()Объявите уникальный ключ для каждого события.
EventHandlerListсохраняет делегаты по ключу.static readonlyИспользуйте объект (Shared ReadOnlyв Visual Basic) для каждого ключа— удостоверение объекта гарантирует, что каждый ключ действительно уникальный:static readonly object temperatureChangedKey = new(); static readonly object humidityChangedKey = new(); static readonly object pressureChangedKey = new(); static readonly object batteryLowKey = new(); static readonly object signalLostKey = new(); static readonly object signalRestoredKey = new(); static readonly object thresholdExceededKey = new(); static readonly object calibrationRequiredKey = new(); static readonly object dataReceivedKey = new(); static readonly object errorDetectedKey = new();Shared ReadOnly temperatureChangedKey As New Object() Shared ReadOnly humidityChangedKey As New Object() Shared ReadOnly pressureChangedKey As New Object() Shared ReadOnly batteryLowKey As New Object() Shared ReadOnly signalLostKey As New Object() Shared ReadOnly signalRestoredKey As New Object() Shared ReadOnly thresholdExceededKey As New Object() Shared ReadOnly calibrationRequiredKey As New Object() Shared ReadOnly dataReceivedKey As New Object() Shared ReadOnly errorDetectedKey As New Object()Определите каждое событие в виде свойства события с пользовательскими аксессорами добавления и удаления.
Каждый метод доступа вызывает
AddHandlerилиRemoveHandlerна списке, используя ключ связанный с этим событием. В C#также добавьтеprotected virtualметод вызова, который извлекает делегат из списка по ключу и вызывает его. В Visual Basic объявление уже включаетCustom Eventблок,RaiseEventкоторый делает это:public event EventHandler<SensorEventArgs> TemperatureChanged { add { listEventDelegates.AddHandler(temperatureChangedKey, value); } remove { listEventDelegates.RemoveHandler(temperatureChangedKey, value); } } protected virtual void OnTemperatureChanged(SensorEventArgs e) => ((EventHandler<SensorEventArgs>?)listEventDelegates[temperatureChangedKey])?.Invoke(this, e);Public Custom Event TemperatureChanged As EventHandler(Of SensorEventArgs) AddHandler(Value As EventHandler(Of SensorEventArgs)) listEventDelegates.AddHandler(temperatureChangedKey, Value) End AddHandler RemoveHandler(Value As EventHandler(Of SensorEventArgs)) listEventDelegates.RemoveHandler(temperatureChangedKey, Value) End RemoveHandler RaiseEvent(sender As Object, e As SensorEventArgs) CType(listEventDelegates(temperatureChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e) End RaiseEvent End EventПовторите этот шаблон для каждого события, используя соответствующий ключ.
Подпишитесь на событие с помощью
+=оператора (в Visual Basic,AddHandler):sensor.TemperatureChanged += Sensor_TemperatureChanged;AddHandler sensor.TemperatureChanged, AddressOf Sensor_TemperatureChangedОпределите обработчик событий.
Подпись должна соответствовать делегату EventHandler<TEventArgs>
object— отправителю и классу данных событий в качестве второго параметра:static void Sensor_TemperatureChanged(object? sender, SensorEventArgs e) => Console.WriteLine($"Sensor {e.SensorId}: temperature changed to {e.Value}.");Sub Sensor_TemperatureChanged(sender As Object, e As SensorEventArgs) Console.WriteLine("Sensor {0}: temperature changed to {1}.", e.SensorId, e.Value) End Sub
В следующем примере показана полная Sensor реализация класса:
using System.ComponentModel;
public class SensorEventArgs(string sensorId, double value) : EventArgs
{
public string SensorId { get; } = sensorId;
public double Value { get; } = value;
}
// Sensor defines 10 event properties backed by a single EventHandlerList.
// EventHandlerList is memory-efficient for classes with many events: it only
// allocates storage for events that have active subscribers.
class Sensor
{
protected EventHandlerList listEventDelegates = new();
static readonly object temperatureChangedKey = new();
static readonly object humidityChangedKey = new();
static readonly object pressureChangedKey = new();
static readonly object batteryLowKey = new();
static readonly object signalLostKey = new();
static readonly object signalRestoredKey = new();
static readonly object thresholdExceededKey = new();
static readonly object calibrationRequiredKey = new();
static readonly object dataReceivedKey = new();
static readonly object errorDetectedKey = new();
public event EventHandler<SensorEventArgs> TemperatureChanged
{
add { listEventDelegates.AddHandler(temperatureChangedKey, value); }
remove { listEventDelegates.RemoveHandler(temperatureChangedKey, value); }
}
protected virtual void OnTemperatureChanged(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[temperatureChangedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> HumidityChanged
{
add { listEventDelegates.AddHandler(humidityChangedKey, value); }
remove { listEventDelegates.RemoveHandler(humidityChangedKey, value); }
}
protected virtual void OnHumidityChanged(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[humidityChangedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> PressureChanged
{
add { listEventDelegates.AddHandler(pressureChangedKey, value); }
remove { listEventDelegates.RemoveHandler(pressureChangedKey, value); }
}
protected virtual void OnPressureChanged(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[pressureChangedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> BatteryLow
{
add { listEventDelegates.AddHandler(batteryLowKey, value); }
remove { listEventDelegates.RemoveHandler(batteryLowKey, value); }
}
protected virtual void OnBatteryLow(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[batteryLowKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> SignalLost
{
add { listEventDelegates.AddHandler(signalLostKey, value); }
remove { listEventDelegates.RemoveHandler(signalLostKey, value); }
}
protected virtual void OnSignalLost(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[signalLostKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> SignalRestored
{
add { listEventDelegates.AddHandler(signalRestoredKey, value); }
remove { listEventDelegates.RemoveHandler(signalRestoredKey, value); }
}
protected virtual void OnSignalRestored(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[signalRestoredKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> ThresholdExceeded
{
add { listEventDelegates.AddHandler(thresholdExceededKey, value); }
remove { listEventDelegates.RemoveHandler(thresholdExceededKey, value); }
}
protected virtual void OnThresholdExceeded(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[thresholdExceededKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> CalibrationRequired
{
add { listEventDelegates.AddHandler(calibrationRequiredKey, value); }
remove { listEventDelegates.RemoveHandler(calibrationRequiredKey, value); }
}
protected virtual void OnCalibrationRequired(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[calibrationRequiredKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> DataReceived
{
add { listEventDelegates.AddHandler(dataReceivedKey, value); }
remove { listEventDelegates.RemoveHandler(dataReceivedKey, value); }
}
protected virtual void OnDataReceived(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[dataReceivedKey])?.Invoke(this, e);
public event EventHandler<SensorEventArgs> ErrorDetected
{
add { listEventDelegates.AddHandler(errorDetectedKey, value); }
remove { listEventDelegates.RemoveHandler(errorDetectedKey, value); }
}
protected virtual void OnErrorDetected(SensorEventArgs e) =>
((EventHandler<SensorEventArgs>?)listEventDelegates[errorDetectedKey])?.Invoke(this, e);
}
Imports System.ComponentModel
Public Class SensorEventArgs
Inherits EventArgs
Public ReadOnly Property SensorId As String
Public ReadOnly Property Value As Double
Public Sub New(sensorId As String, value As Double)
Me.SensorId = sensorId
Me.Value = value
End Sub
End Class
' Sensor defines 10 event properties backed by a single EventHandlerList.
' EventHandlerList is memory-efficient for classes with many events: it only
' allocates storage for events that have active subscribers.
Class Sensor
Protected listEventDelegates As New EventHandlerList()
Shared ReadOnly temperatureChangedKey As New Object()
Shared ReadOnly humidityChangedKey As New Object()
Shared ReadOnly pressureChangedKey As New Object()
Shared ReadOnly batteryLowKey As New Object()
Shared ReadOnly signalLostKey As New Object()
Shared ReadOnly signalRestoredKey As New Object()
Shared ReadOnly thresholdExceededKey As New Object()
Shared ReadOnly calibrationRequiredKey As New Object()
Shared ReadOnly dataReceivedKey As New Object()
Shared ReadOnly errorDetectedKey As New Object()
Public Custom Event TemperatureChanged As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(temperatureChangedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(temperatureChangedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(temperatureChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event HumidityChanged As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(humidityChangedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(humidityChangedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(humidityChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event PressureChanged As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(pressureChangedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(pressureChangedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(pressureChangedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event BatteryLow As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(batteryLowKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(batteryLowKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(batteryLowKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event SignalLost As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(signalLostKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(signalLostKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(signalLostKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event SignalRestored As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(signalRestoredKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(signalRestoredKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(signalRestoredKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event ThresholdExceeded As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(thresholdExceededKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(thresholdExceededKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(thresholdExceededKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event CalibrationRequired As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(calibrationRequiredKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(calibrationRequiredKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(calibrationRequiredKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event DataReceived As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(dataReceivedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(dataReceivedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(dataReceivedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
Public Custom Event ErrorDetected As EventHandler(Of SensorEventArgs)
AddHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.AddHandler(errorDetectedKey, Value)
End AddHandler
RemoveHandler(Value As EventHandler(Of SensorEventArgs))
listEventDelegates.RemoveHandler(errorDetectedKey, Value)
End RemoveHandler
RaiseEvent(sender As Object, e As SensorEventArgs)
CType(listEventDelegates(errorDetectedKey), EventHandler(Of SensorEventArgs))?.Invoke(sender, e)
End RaiseEvent
End Event
End Class