C#固定时间执行指定事件(观察者模式+异步委托)

Posted %幻#影%

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#固定时间执行指定事件(观察者模式+异步委托)相关的知识,希望对你有一定的参考价值。

最近有个项目需要每天固定的时间去执行指定的事件,发现网上关于这样的文章比较少,而且比较散。通过学习了几篇文章后终于实现了这个功能,在此也特别感谢这些文章的作者们,这也是我第一次在园子里面发文章,望多指教。

关于观察者模式,我在这里就不做讲解了,如有不懂,可以参考相关文章。

那么开始入正题。

主要有三个页面:Observer.cs(观察者)、Subject.cs(通知者)、Form1.cs

Observer.cs

复制代码
class Observer
    {
        /// <summary>
        /// 执行事件A
        /// </summary>
        /// <returns></returns>
        public string DoA()
        {
            return "时间到了,执行事件A~~";
        }

        /// <summary>
        ///执行事件B
        /// </summary>
        /// <returns></returns>
        public string DoB()
        {
            return "时间到了,执行事件B~~";
        }

    }
复制代码

Subject.cs(用于通知观察者的类)

复制代码
namespace XXXXXX
{
    //声明委托
    delegate string EventHandler();
    class Subject
    {
        //声明事件
        public event EventHandler Output;
        public string Notify()
        {
            string res = "";
            if (Output != null)
            {
                res = Output();
            }
            return res;
        }
  }
}
复制代码

Form1.cs

使用了TextBox控件txtShow和Timer控件timer,timer的时间间隔设为1s

复制代码
private void timer_Tick(object sender, EventArgs e)
        {
            
           Subject subject = new Subject();
            Observer observer = new Observer();
            string now = DateTime.Now.ToString("HH:mm:ss");
            //设置固定时间要执行的事件
            switch (now)
            {
                case "22:28:00":
                    subject.Output += new EventHandler(observer.DoA);
                    break;
                case "22:29:00":
                    subject.Output += new EventHandler(observer.DoB);
                    break;
            }
            string res = "";
            //执行事件
            res += subject.Notify();
            if (res != "")
            {
                txtShow.AppendText(now + ":");
                txtShow.AppendText(res);
                txtShow.AppendText("\\r\\n");
            }
}
复制代码

 结果:

 

 

但以上的方法是同步的,也就是第一个方法执行太久的话会影响第二个方法的执行,那么要解决这问题,下面就用到异步委托。

Observer.cs不用修改到,这也是用了观察者模式所带来的好处。

Subject.cs(修改了Notify方法,添加了一个委托、事件和方法)

复制代码
namespace XXXX
{
    //声明委托
    delegate string EventHandler();
    delegate void ShowInfoHandler(string info);
    class Subject
    {
        //声明事件
        public event EventHandler Output;
        public event ShowInfoHandler ShowInfoEvent;
       

        public void Notify()
        {
           
            if (Output != null)
            {
                foreach(EventHandler handler in Output.GetInvocationList())
                {
                    //异步调用委托,第一个参数为要回调的函数,第二个参数为要向回调函数传入的值
                    //这里传入被调用方法的委托
                    handler.BeginInvoke(CallBack, handler);
                    
                }
            }
            
        }

        /// <summary>
        /// 回调函数
        /// </summary>
        /// <param name="show"></param>
        public void CallBack(IAsyncResult obj)
        {
            EventHandler handler = (EventHandler)obj.AsyncState;
            //获取被调用方法的返回的信息
            string res= handler.EndInvoke(obj);
            ShowInfoEvent(res);
        }

    }
}
复制代码

这里稍微解释一下。ShowInfoHandler、ShowInfoEvent用于向主线程txtShow输出提示信息用的,若不用输出提示信息可以省去。(Form1.cs会用到)

handler.BeginInvoke调用异步委托,第一个参数传入要回调的函数,也就是执行完自身的方法后会继续执行的方法;第二个参数一般传入自身的委托,方便在回调函数中获取执行完返回的信息。

Form1.cs

复制代码
 //非主线程无法操作界面的控件,所以用委托来实现向txtShow输出信息
        public void ShowInfo(string info)
        {
            txtShow.Invoke(new Action(()=>{txtShow.AppendText(info+"\\r\\n");}));
        }

        private void timer_Tick(object sender, EventArgs e)
        {
            
            
            Subject subject = new Subject();
            Observer observer = new Observer();
            //将向txtShow输出信息的方法交给subject的委托
            subject.ShowInfoEvent += new ShowInfoHandler(ShowInfo);
            string now = DateTime.Now.ToString("HH:mm:ss");
            switch (now)
            {
                case "23:20:00":
                    txtShow.AppendText("现在时间:"+now+"\\r\\n");
                    subject.Output += new EventHandler(observer.DoA);
                    
                    break;
                case "23:21:00":
                    txtShow.AppendText("现在时间:"+now+"\\r\\n");
                    subject.Output += new EventHandler(observer.DoB);
                    break;
            }
            subject.Notify();
            
            
        }
复制代码

子线程操作主线程的控件还有其他方法,大家可以尝试下,这里就不整理了。

结果:

http://www.cnblogs.com/chenjiguang/p/4271356.html

以上是关于C#固定时间执行指定事件(观察者模式+异步委托)的主要内容,如果未能解决你的问题,请参考以下文章

C# 委托和事件 与 观察者模式(发布-订阅模式)讲解 by天命

利用事件委托弥补观察者模式不足

C# Winform 多线程异步委托进度条

C#综合揭秘——深入分析委托与事件

UNITY_委托和事件

C#如何使用异步编程