標籤:無法 for state 網上 好處 back 修改 call 通過
最近有個項目需要每天固定的時間去執行指定的事件,發現網上關於這樣的文章比較少,而且比較散。通過學習了幾篇文章後終於實現了這個功能,在此也特別感謝這些文章的作者們,這也是我第一次在園子裡面發文章,望多指教。
關於觀察者模式,我在這裡就不做講解了,如有不懂,可以參考相關文章。
那麼開始入正題。
主要有三個頁面: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#固定時間執行指定事件(觀察者模式+非同步委託)