zoukankan      html  css  js  c++  java
  • 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>替换就行了。具体情况具体分析,这里特意提观察者模式是想说明真的懒不想写随笔,还有重要的一点就是设计模式很值得学习。
  • 相关阅读:
    全国疫情数据的爬取
    Spring_声明式事务
    第三周总结
    Spring_整合Mybatis
    Oracle AWR内容详解 参考学习钱若梨花落
    查看Oracle某时刻的客户端IP连接情况 参考学习钱若梨花落
    oracle Logminer 日志挖掘 参考学习钱若离花落
    静默升级oracle 11g (从11.2.0.1升级到11.2.0.4)
    oracle RAC集群启动和关闭
    856. Score of Parentheses
  • 原文地址:https://www.cnblogs.com/xuanhu/p/9690904.html
Copyright © 2011-2022 走看看