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();

        }

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

结果:

时间: 2024-10-26 21:58:34

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

Windows 添加计划任务 每隔一定时间执行指定批处理脚本

schtasks /create /sc minute /mo 20 /tn "TestBatch" /tr C:/TestBatch.bat TestBatch.bat echo "---------------------批处理开始------------------------------"ping sz.tencent.com > D:/a.txtping sz1.tencent.com >> D:a.txtping sz2.tencent

java Timer(定时调用、实现固定时间执行)

最近需要用到定时调用的功能.可以通过java的Timer类来进行定时调用,下面是有关Timer的一些相关知识. 其实就Timer来讲就是一个调度器,而TimerTask呢只是一个实现了run方法的一个类,而具体的TimerTask需要由你自己来实现,例如这样: Timer timer = new Timer(); timer.schedule(new TimerTask() { public void run() { System.out.println("11232"); } },

C#使用Timer.Interval指定时间间隔与指定时间执行事件

C#中,Timer是一个定时器,它可以按照指定的时间间隔或者指定的时间执行一个事件. 指定时间间隔是指按特定的时间间隔,如每1分钟.每10分钟.每1个小时等执行指定事件: 指定时间是指每小时的第30分.每天10:30:30(每天的10点30分30秒)等执行指定的事件: 在上述两种情况下,都需要使用 Timer.Interval,方法如下: 1.按特定的时间间隔: using System; using System.Timers; namespace TimerExample { class P

android ScheduleExecutorService定时周期执行指定任务

一:简单说明 ScheduleExecutorService接口中有四个重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在实现定时程序时比较方便. 下面是该接口的原型定义 java.util.concurrent.ScheduleExecutorService extends ExecutorService extends Executor 接口scheduleAtFixedRate原型定义及参数说明 [java] view plaincopy

C# 1.0 特性之异步委托(AP、APM)

?  前言 C# 异步委托也是属于异步编程中的一种,可以称为 Asynchronous Programming(异步编程)或者 Asynchronous Programming Model(异步编程模型),因为这是实现异步编程的模式.委托是 C#1.0 就有的特性,并且 .NET v1.0 同时也伴随有 AsyncCallback.IAsyncResult 等类/接口的出现,所以所有的 .NET 版本中都是支持的. 1.   什么是异步委托 1)   异步委托是采用异步回调的方式实现异步执行,当

Linux 命令 - at: 在指定的时间执行任务

在指定的时间执行任务. 命令格式 at [-V] [-q queue] [-f file] [-mldbv] TIMEat [-V] [-q queue] [-f file] [-mldbv] -t time_argat -c job [job...] 命令参数 -V 在标准错误流上打印版本号 -q queue 使用指定的队列.一个队列以单一的字母命名,有效的命名范围是 a-z 和 A-Z.at 命令的缺省队列是 a,batch 命令的缺省队列是 b.字母的顺序越高,队列的优先级则越低.特殊队列

sql语句延时执行或者是指定时间执行

--使用waitfor语句延迟或暂停程序的执行 --waitfor{delay'time'|time 'time'} delay是指间隔时间 最长到24小时 time是指定时间执行 waitfor delay '00:00:10' --延迟10秒 A. 使用 WAITFOR TIME 以下示例在晚上 10:20 (22:20) 执行存储过程 sp_update_job. USE msdb; EXECUTE sp_add_job @job_name = 'TestJob'; BEGIN WAITF

启动系统定时器,每隔1分钟/指定时间执行任务 学习笔记

import java.util.Calendar; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class DemoTimer { //启动系统定时器,每隔1分钟/指定时间执行任务 //java.util.Timer定时器是以后台线程方式控制运行,它是线程安全,无需手工加锁 public static void main(String[] args) { //创建定时器 Ti

MSDN搬运 之 [基于事件的异步模式]

基于事件的异步模式概述 那些同时执行多项任务.但仍能响应用户交互的应用程序通常需要实施一种使用多线程的设计方案.System.Threading 命名空间提供了创建高性能多线程应用程序所必需的所有工具,但要想有效地使用这些工具,需要有丰富的使用多线程软件工程的经验.对于相对简单的多线程应用程序,BackgroundWorker 组件提供了一个简单的解决方案.对于更复杂的异步应用程序,请考虑实现一个符合基于事件的异步模式的类. 基于事件的异步模式具有多线程应用程序的优点,同时隐匿了多线程设计中固有