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>替换就行了。具体情况具体分析,这里特意提观察者模式是想说明真的懒不想写随笔,还有重要的一点就是设计模式很值得学习。
优质内容筛选与推荐>>
1、ASP.NET中在线用户统计
2、反射----动态调用方法
3、干货 | 强化学习在携程酒店推荐排序中的应用探索 原创: 宣云儿 携程技术中心 今天干货 | 强化学习在携程酒店推荐排序中的应用探索 原创: 宣云儿 携程技术中心 今天
4、Windows mobile 获取当前路径
5、文本处理工具sed


长按二维码向我转账

受苹果公司新规定影响,微信 iOS 版的赞赏功能被关闭,可通过二维码转账支持公众号。

    阅读
    好看
    已推荐到看一看
    你的朋友可以在“发现”-“看一看”看到你认为好看的文章。
    已取消,“好看”想法已同步删除
    已推荐到看一看 和朋友分享想法
    最多200字,当前共 发送

    已发送

    朋友将在看一看看到

    确定
    分享你的想法...
    取消

    分享想法到看一看

    确定
    最多200字,当前共

    发送中

    网络异常,请稍后重试

    微信扫一扫
    关注该公众号





    联系我们

    欢迎来到TinyMind。

    关于TinyMind的内容或商务合作、网站建议,举报不良信息等均可联系我们。

    TinyMind客服邮箱:support@tinymind.net.cn