1.前言
事件是以委托为基础的,掌握委托相关知识后理解事件事半功倍。
事件通过委托绑定触发时需要处理的方法,C#使用事件机制实现线程之间的消息通知。
2.自定义事件
定义一个事件需要先定义一个委托,再用这个委托定义一个事件。
再开放一个事件触发的方法,用于其他类或线程等进行调用触发。
public class ClassA
{
public delegate void DisplayPlaneEventHandler(); // 显示图层委托
public event DisplayPlaneEventHandler DisplayPlaneChangedEvent; // 显示图层事件
/// <summary>
/// 事件触发
/// </summary>
public void UpdateDispPlane()
{
//显示图层事件
if (DisplayPlaneChangedEvent != null)
{
//DisplayPlaneChangedEvent?.Invoke();
DisplayPlaneChangedEvent();
}
}
}
在其他类中注册事件触发后响应的执行方法,当执行事件触发时,该响应的执行方法将会执行。
public class ClassB
{
private ClassA sampleA;
public ClassB()
{
sampleA = new ClassA();
sampleA.DisplayPlaneChangedEvent += DispView; //注册响应事件
}
/// <summary>
/// 响应事件的方法
/// </summary>
private void DispView()
{
//响应事件触发的执行内容
}
/// <summary>
/// 执行事件触发
/// </summary>
private void Excute()
{
sampleA.UpdateDispPlane();
}
}
3. .NET事件
.NET提供了两种默认的事件委托:
(1)不带输入参数的事件委托:EventHandler
public delegate void EventHandler(object? sender, EventArgs e);
EventArgs可用EventArgs.Empty触发事件:
class ProgramOne
{
static void Main(string[] args)
{
Counter c = new Counter(new Random().Next(10));
c.ThresholdReached += c_ThresholdReached;
Console.WriteLine("press 'a' key to increase total");
while (Console.ReadKey(true).KeyChar == 'a')
{
Console.WriteLine("adding one");
c.Add(1);
}
}
static void c_ThresholdReached(object sender, EventArgs e)
{
Console.WriteLine("The threshold was reached.");
Environment.Exit(0);
}
}
class Counter
{
private int threshold;
private int total;
public Counter(int passedThreshold)
{
threshold = passedThreshold;
}
public void Add(int x)
{
total += x;
if (total >= threshold)
{
ThresholdReached?.Invoke(this, EventArgs.Empty);
}
}
public event EventHandler ThresholdReached;
}
(2)带输入参数的事件委托:EventHandler<TEventArgs>
public delegate void EventHandler<TEventArgs>(object? sender, TEventArgs e);
TEventArgs的输入参数类型可通过继承EventArgs的方式进行自定义,实现向事件中传入需要的参数:
class ProgramThree
{
static void Main(string[] args)
{
Counter c = new Counter(new Random().Next(10));
c.ThresholdReached += c_ThresholdReached;
Console.WriteLine("press 'a' key to increase total");
while (Console.ReadKey(true).KeyChar == 'a')
{
Console.WriteLine("adding one");
c.Add(1);
}
}
static void c_ThresholdReached(object sender, ThresholdReachedEventArgs e)
{
Console.WriteLine("The threshold of {0} was reached at {1}.", e.Threshold, e.TimeReached);
Environment.Exit(0);
}
}
class Counter
{
private int threshold;
private int total;
public Counter(int passedThreshold)
{
threshold = passedThreshold;
}
public void Add(int x)
{
total += x;
if (total >= threshold)
{
ThresholdReachedEventArgs args = new ThresholdReachedEventArgs();
args.Threshold = threshold;
args.TimeReached = DateTime.Now;
OnThresholdReached(args);
}
}
protected virtual void OnThresholdReached(ThresholdReachedEventArgs e)
{
EventHandler<ThresholdReachedEventArgs> handler = ThresholdReached;
if (handler != null)
{
handler(this, e);
}
}
public event EventHandler<ThresholdReachedEventArgs> ThresholdReached;
}
public class ThresholdReachedEventArgs : EventArgs
{
public int Threshold { get; set; }
public DateTime TimeReached { get; set; }
}
3.总结
基于.NET提供的两种事件委托可以实现大部分的事件需求,很少需要自定义事件委托。