C# 委托还能这样用

一直找不到一种能够让很多对象都能在几乎同时接收到通知的方法。介绍下目前在用的,希望能够抛砖引玉。

首先随便贴一下观察者模式的两接口,观察者模式自行搜索设计模式。

    public interface ISubject<T> where T : class
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="action">为true表示注册,false表示注销</param>
        int RegistNotify(bool action, IObserver<T> ob);
    }

    public interface IObserver<T> where T : class
    {
        void MessageNotify(T message);
    }

ISubject接口对象作为通知发起者,IObserver接口对象即为要接收通知的对象了。

写个类实现IOserver接口。

    class Observer : ObserverPattern.IObserver<Msg>
    {
        public Observer(ISubject<Msg> sub)
        {
            sub.RegistNotify(true, this);  // 注册
        }

        void ObserverPattern.IObserver<Msg>.MessageNotify(Msg message)
        {
            DateTime cur = DateTime.Now;  // 当接收到通知时记录下当前时间
            Debug.WriteLine("s : " + cur.Second + " ms : " + cur.Millisecond);
        }
    }

建了个窗体实现ISubject接口。

    public partial class Form1 : Form, ISubject<Msg>
    {
        List<ObserverPattern.IObserver<Msg>> m_observers;

        public Form1()
        {
            InitializeComponent();
            this.Load += Form1_Load;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            m_observers = new List<ObserverPattern.IObserver<Msg>>();

            Observer ob = new Observer(this);
            Observer ob2 = new Observer(this);
            Observer ob3 = new Observer(this);
            Observer ob4 = new Observer(this);
            Observer ob5 = new Observer(this);
            Observer ob6 = new Observer(this);
            Observer ob7 = new Observer(this);
            Observer ob8 = new Observer(this);
            Observer ob9 = new Observer(this);
            Observer ob10 = new Observer(this);
            Observer ob11 = new Observer(this);
            Observer ob12 = new Observer(this);
            Observer ob13 = new Observer(this);
            Observer ob14 = new Observer(this);
            Observer ob15 = new Observer(this);
            Observer ob16 = new Observer(this);
            Observer ob17 = new Observer(this);
        }

        int ISubject<Msg>.RegistNotify(bool action, ObserverPattern.IObserver<Msg> ob)
        {
            if (action) { m_observers.Add(ob); return 0; }
            m_observers.Remove(ob);
            return 0;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Msg message = new Msg() { Ident = 1, Data = null };

            foreach (var ob in m_observers)
            {
                Task.Factory.StartNew(() => ob.MessageNotify(message));
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Msg message = new Msg() { Ident = 2, Data = null };

            foreach (var ob in m_observers)
            {
                new Thread(() => { ob.MessageNotify(message); }) { IsBackground = true, }.Start();
            }
        }

    }
}

加载了17个观察者。

分别用任务方式和线程方式发起通知。此例中观察者少所以差别不太明显,但如果观察者多的话频繁创建线程肯定消耗资源。推荐任务方式,但还是没达到我想要的效果,比如在5ms内能通知到100个观察者?[突然想到网络发包这么快,有时间通过这个点思考下。]

以下是输出:

任务方式,耗时208ms--------------------------------------------

s : 31 ms : 350
s : 31 ms : 350
s : 31 ms : 372
s : 31 ms : 418
s : 31 ms : 420
s : 31 ms : 422
s : 31 ms : 423
s : 31 ms : 396
s : 31 ms : 425
s : 31 ms : 446
s : 31 ms : 469
s : 31 ms : 490
s : 31 ms : 513
s : 31 ms : 536
s : 31 ms : 558
s : 31 ms : 349
s : 31 ms : 396

线程方式,耗时225ms--------------------------------------------

s : 46 ms : 523
线程 0x10854 已退出,返回值为 0 (0x0)。
s : 46 ms : 525
线程 0x10230 已退出,返回值为 0 (0x0)。
s : 46 ms : 548
线程 0xcc84 已退出,返回值为 0 (0x0)。
s : 46 ms : 570
线程 0xea48 已退出,返回值为 0 (0x0)。
s : 46 ms : 593
线程 0x10524 已退出,返回值为 0 (0x0)。
s : 46 ms : 618
线程 0x3308 已退出,返回值为 0 (0x0)。
s : 46 ms : 643
线程 0x10d58 已退出,返回值为 0 (0x0)。
s : 46 ms : 646
线程 0xe808 已退出,返回值为 0 (0x0)。
s : 46 ms : 648
线程 0xe684 已退出,返回值为 0 (0x0)。
s : 46 ms : 651
线程 0x10c5c 已退出,返回值为 0 (0x0)。
s : 46 ms : 674
线程 0xecc0 已退出,返回值为 0 (0x0)。
s : 46 ms : 675
线程 0x10508 已退出,返回值为 0 (0x0)。
s : 46 ms : 698
s : 46 ms : 735
s : 46 ms : 743
线程 0xe5d0 已退出,返回值为 0 (0x0)。
线程 0x10dd4 已退出,返回值为 0 (0x0)。
线程 0x10a80 已退出,返回值为 0 (0x0)。
s : 46 ms : 747
线程 0x10e30 已退出,返回值为 0 (0x0)。
s : 46 ms : 748
线程 0xf754 已退出,返回值为 0 (0x0)。
线程 0xe90c 已退出,返回值为 0 (0x0)。
线程 0x10bd4 已退出,返回值为 0 (0x0)。
线程 0x10ed4 已退出,返回值为 0 (0x0)。
线程 0xc958 已退出,返回值为 0 (0x0)。
线程 0xe5fc 已退出,返回值为 0 (0x0)。
线程 0x109fc 已退出,返回值为 0 (0x0)。

本来不想写太多,可还是花了点时间。最后填下标题的坑哈,毕竟全文一个委托都没提:

把IObserver接口中的MessageNotify(T message)用一个Action<T>替换就行了。具体情况具体分析,这里特意提观察者模式是想说明真的懒不想写随笔,还有重要的一点就是设计模式很值得学习。
posted @ 2018-09-22 19:21  不会吉他的程序员  阅读(438)  评论(0编辑  收藏  举报