问题:

有一些初始化操作,需要在整个程序运行过程中,只运行一次。除了使用单例模式,或者在 Main() 中实现,还有其他方法么?

比如,有一个任务处理程序,每次点击Run按钮,程序就会调用一个静态类StepsProcessor.cs中的ProcessSteps()方法依次对指定的任务列表进行处理。这个静态类会发布三个事件:

  1. 开始执行任务列表
  2. 全部任务执行成功
  3. 某个任务执行失败

使用静态类的构造函数,让某些操作在整个程序运行过程中只运行一次

针对这些事件,有多个事件订阅者,会在这些事件发生时作一些动作,比如发邮件。在静态类 StepsProcessor.cs 中,有静态方法 RegisterEvents() 将所有的事件订阅者与这些事件绑定起来。原来的代码将Run按钮的Click事件中,调用了 StepsProcessor.RegisterEvents() 事件,这样导致一个问题,当第二次点击Run按钮时,就会将已经绑定的事件订阅者再次绑定,于是对于同一事件,同样的订阅者,会被执行两次(比如,会连续发两次邮件,报告“开始执行任务列表”,也会连续发两次邮件,报告“全部任务执行成功”);当第二轮任务全部跑完,再次点击Run按钮开始第三轮时,同样的订阅者会被执行三次(比如,连续发送三封同样的邮件)。

如果以最少的代码改动,修正这个逻辑陷呢?

原因:

RegisterEvents() 方法,只会遍历所有的事件订阅者,调用它们的订阅方法(Subscribe()),将它们与事件发布者绑定起来。而在绑定之前,并不检查是否已经绑定过,就导致了同一个订阅者,会有多个实例与事件发布者相关联。

解决方案:

可以将这个初始化操作RegisterEvents()放在静态类StepsProcessor.cs的构造函数中。从而保证这个RegisterEvents()只会被执行一次,而不是每次点击按钮都执行。

    /// 
    /// A wrapper to run the specified steps.
    /// 
    public static class StepsProcessor
    {
        static StepsProcessor()
        {
            // Should only register the events once during all the lifecycle of this program, 
            // so put it here inside a static constructor:
            RegisterEvents();
        }
	...
    }