事件

事件指一个用户操作,如按键、点击、移动鼠标等,也可以是系统生成的通知。当事件发生时,应用需要对其作出相应的反应,如中断。另外,事件也用于内部进程通信。

通过事件使用委托

事件生成于类的声明中,通过使用同一个类或其他类中的委托与事件处理程序关联。包含事件的类用于发布事件,称为发布器类。其他接受该事件的类称为订阅器类。事件使用的是发布-订阅(publisher-subscriber)模型。

发布器是一个定义了事件和委托的对象,此外还定义了事件和委托之间的联系。一个发布器类的对象调用这个事件,同时通知其他的对象。

订阅器是一个接受事件并提供事件处理程序的对象。在发布器类中的委托调用订阅器类中的方法(或事件处理程序)。

声明事件

在类中声明一个事件,首先需要声明该事件对应的委托类型。如:

  1. public delegate void BoilerLogHandler(string status);

其次为使用 event 关键字来声明这个事件:

  1. //基于上述委托定义事件
  2. public event BoilerLogHandler BoilerEventLog;

上述代码段定义了一个名为 BoilerLogHandler 的委托以及一个名为 BoilerEventLog 的事件,该事件生成时会自动调用委托。

示例 1

  1. using System;
  2. namespace SimpleEvent
  3. {
  4. using System;
  5. public class EventTest
  6. {
  7. private int value;
  8. public delegate void NumManipulationHandler();
  9. public event NumManipulationHandler ChangeNum;
  10. protected virtual void OnNumChanged()
  11. {
  12. if (ChangeNum != null)
  13. {
  14. ChangeNum();
  15. }
  16. else
  17. {
  18. Console.WriteLine("Event fired!");
  19. }
  20. }
  21. public EventTest(int n )
  22. {
  23. SetValue(n);
  24. }
  25. public void SetValue(int n)
  26. {
  27. if (value != n)
  28. {
  29. value = n;
  30. OnNumChanged();
  31. }
  32. }
  33. }
  34. public class MainClass
  35. {
  36. public static void Main()
  37. {
  38. EventTest e = new EventTest(5);
  39. e.SetValue(7);
  40. e.SetValue(11);
  41. Console.ReadKey();
  42. }
  43. }
  44. }

编译执行上述代码,得到如下结果:

  1. Event Fired!
  2. Event Fired!
  3. Event Fired!

示例 2

该示例为一个简单的应用程序,该程序用于热水锅炉系统故障排除。当维修工程师检查锅炉时,锅炉的温度、压力以及工程师所写的备注都会被自动记录到一个日志文件中。

  1. using System;
  2. using System.IO;
  3. namespace BoilerEventAppl
  4. {
  5. // boiler 类
  6. class Boiler
  7. {
  8. private int temp;
  9. private int pressure;
  10. public Boiler(int t, int p)
  11. {
  12. temp = t;
  13. pressure = p;
  14. }
  15. public int getTemp()
  16. {
  17. return temp;
  18. }
  19. public int getPressure()
  20. {
  21. return pressure;
  22. }
  23. }
  24. // 事件发布器
  25. class DelegateBoilerEvent
  26. {
  27. public delegate void BoilerLogHandler(string status);
  28. // 基于上述委托定义事件
  29. public event BoilerLogHandler BoilerEventLog;
  30. public void LogProcess()
  31. {
  32. string remarks = "O. K";
  33. Boiler b = new Boiler(100, 12);
  34. int t = b.getTemp();
  35. int p = b.getPressure();
  36. if(t > 150 || t < 80 || p < 12 || p > 15)
  37. {
  38. remarks = "Need Maintenance";
  39. }
  40. OnBoilerEventLog("Logging Info:\n");
  41. OnBoilerEventLog("Temparature " + t + "\nPressure: " + p);
  42. OnBoilerEventLog("\nMessage: " + remarks);
  43. }
  44. protected void OnBoilerEventLog(string message)
  45. {
  46. if (BoilerEventLog != null)
  47. {
  48. BoilerEventLog(message);
  49. }
  50. }
  51. }
  52. // 该类保留写入日志文件的条款
  53. class BoilerInfoLogger
  54. {
  55. FileStream fs;
  56. StreamWriter sw;
  57. public BoilerInfoLogger(string filename)
  58. {
  59. fs = new FileStream(filename, FileMode.Append, FileAccess.Write);
  60. sw = new StreamWriter(fs);
  61. }
  62. public void Logger(string info)
  63. {
  64. sw.WriteLine(info);
  65. }
  66. public void Close()
  67. {
  68. sw.Close();
  69. fs.Close();
  70. }
  71. }
  72. // 事件订阅器
  73. public class RecordBoilerInfo
  74. {
  75. static void Logger(string info)
  76. {
  77. Console.WriteLine(info);
  78. }//end of Logger
  79. static void Main(string[] args)
  80. {
  81. BoilerInfoLogger filelog = new BoilerInfoLogger("e:\\boiler.txt");
  82. DelegateBoilerEvent boilerEvent = new DelegateBoilerEvent();
  83. boilerEvent.BoilerEventLog += new
  84. DelegateBoilerEvent.BoilerLogHandler(Logger);
  85. boilerEvent.BoilerEventLog += new
  86. DelegateBoilerEvent.BoilerLogHandler(filelog.Logger);
  87. boilerEvent.LogProcess();
  88. Console.ReadLine();
  89. filelog.Close();
  90. }//end of main
  91. }//end of RecordBoilerInfo
  92. }

编译执行上述代码,得到如下结果:

  1. Logging info:
  2. Temperature 100
  3. Pressure 12
  4. Message: O. K