程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> C#固定時間執行指定事件(觀察者模式+異步委托),

C#固定時間執行指定事件(觀察者模式+異步委托),

編輯:C#入門知識

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

子線程操作主線程的控件還有其他方法,大家可以嘗試下,這裡就不整理了。

結果:

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved