zoukankan      html  css  js  c++  java
  • 一步一步学Remoting之六:事件(2)

    1)关闭一个客户端以后会影响其他的客户端事件
    原因:客户端没有取消事件订阅就关闭了,触发事件的时候找不到事件订阅者
    解决:遍历委托链,找到异常的对象,从委托链中卸下
    (2)服务器端对客户端广播,客户端能收到其他客户端的事件处理信息
    原因:使用了Singleton模式,共享远程对象
    解决:因为需要远程对象有状态且不共享实例,所以只有客户端激活可以选择

    修改后的服务端:
    using System;
    using System.Collections;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Tcp;
    using System.Runtime.Serialization.Formatters;

    namespace RemoteServer
    {
        class MyServer
        {
            [STAThread]
            static void Main(string[] args)
            {
                RemotingConfiguration.ApplicationName="RemoteObject.MyObject";
                RemotingConfiguration.RegisterActivatedServiceType(typeof(RemoteObject.MyObject));
                BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); 
                BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); 
                serverProvider.TypeFilterLevel = TypeFilterLevel.Full; 
                IDictionary props = new Hashtable(); 
                props["port"]=8888; 
                TcpChannel channel = new TcpChannel(props,clientProvider,serverProvider); 
                ChannelServices.RegisterChannel(channel); 
                Console.ReadLine();
            }
        }
    }
    修改后的远程对象:
    using System;

    namespace RemoteObject
    {
        [Serializable]
        public class MyEventArgs:EventArgs
        {
            private int _rate;
            private string _ip;

            public int Rate
            {
                get
                {
                    return _rate;
                }
            }

            public string IP
            {
                get
                {
                    return _ip;
                }
            }

            public MyEventArgs(int rate,string ip)
            {
                this._rate=rate;
                this._ip=ip;
            }
        }

        public class MyObject:MarshalByRefObject
        {
            public delegate void MyEventHandler(object sender,MyEventArgs e);
            public event MyEventHandler MyEvent;
            public string tmp;

            public int ALongTimeMethod(int a,int b,int time,string ip)
            {
                Console.WriteLine("来自"+ip+"的异步方法开始");
                for(int i=1;i<=10;i++)
                {
                    System.Threading.Thread.Sleep(time);
                    Console.WriteLine("来自"+ip+"的异步方法完成了"+i*10+"%");
                    OnMyEvent(new MyEventArgs(i,ip));
                }
                Console.WriteLine("来自"+ip+"的异步方法结束");
                return a+b;
            }

            protected void OnMyEvent(MyEventArgs e)
            {
                if (MyEvent!=null)
                {
                    foreach(Delegate d in MyEvent.GetInvocationList())
                    {
                        try
                        {
                            ((MyEventHandler)d)(this,e);
                        }
                        catch
                        {
                            MyEvent-=(MyEventHandler)d;
                        }
                    }
                }
            }
        }

        public class EventClass:MarshalByRefObject
        {
            public void MyEvent(object sender,MyEventArgs e)
            {
                if(((MyObject)sender).tmp==e.IP)
                    Console.WriteLine("异步方法完成了"+e.Rate*10+"%");
            } 
        }
    }

    修改后的客户端:
    using System;
    using System.Net;
    using System.Collections;
    using System.Text;
    using System.Runtime.Remoting;
    using System.Runtime.Remoting.Channels;
    using System.Runtime.Remoting.Channels.Tcp;
    using System.Runtime.Serialization.Formatters;

    class MyClient
    {
        private delegate int MyDelegate(int a,int b,int time,string ip);
        private static MyDelegate md;
        static RemoteObject.MyObject app;
        static RemoteObject.EventClass ec;
        static DateTime dt;

        [STAThread]
        static void Main(string[] args)
        {
            dt=DateTime.Now;
            RemotingConfiguration.RegisterActivatedClientType(typeof(RemoteObject.MyObject),"tcp://localhost:8888/RemoteObject.MyObject");
            BinaryServerFormatterSinkProvider serverProvider = new BinaryServerFormatterSinkProvider(); 
            BinaryClientFormatterSinkProvider clientProvider = new BinaryClientFormatterSinkProvider(); 
            serverProvider.TypeFilterLevel = TypeFilterLevel.Full; 
            IDictionary props=new Hashtable(); 
            props["port"]=0; 
            TcpChannel channel = new TcpChannel(props,clientProvider,serverProvider); 
            ChannelServices.RegisterChannel(channel); 
            app=new RemoteObject.MyObject();
            ec=new RemoteObject.EventClass();
            app.MyEvent+=new RemoteObject.MyObject.MyEventHandler(ec.MyEvent);
            md=new MyDelegate(app.ALongTimeMethod);
            AsyncCallback ac=new AsyncCallback(MyClient.CallBack);
            IPHostEntry ipHE=Dns.GetHostByName(Dns.GetHostName());
            Random rnd=new Random(System.Environment.TickCount);
            string ip=ipHE.AddressList[0].ToString()+"("+rnd.Next(100000000).ToString()+")";
            app.tmp=ip;
            IAsyncResult Iar=md.BeginInvoke(1,2,500,ip,ac,null);
            Method();
            Console.WriteLine("用了"+((TimeSpan)(DateTime.Now-dt)).TotalSeconds+"秒");
            ChannelServices.UnregisterChannel(channel);
            Console.ReadLine();
        }

        public static void CallBack(IAsyncResult Iar)
        {
            if(Iar.IsCompleted)
            {
                Console.WriteLine("结果是"+md.EndInvoke(Iar));
                app.MyEvent-=new RemoteObject.MyObject.MyEventHandler(ec.MyEvent);
            }
        } 

        public static void Method()
        {
            Console.WriteLine("主线程方法开始");
            System.Threading.Thread.Sleep(5000);
            Console.WriteLine("主线程方法结束");
        }
    }

    之所以要在ip地址后面跟上随机数,是因为可能在一个机器上会打开多个客户端,需要在这个时候能在服务器端区分多个客户端。

     

    备注:我的所有例子都是在客户端和服务器端部署远程对象的,其实这个做法不是很好,我们应该仅仅把接口部署在两地,远程对象仅仅部署在服务器端即可。

  • 相关阅读:
    vsftp 虚拟用户测试
    RHEL7 MariaDB测试
    安装xenapp后,非管理员连接RDP出现桌面当前不可用的解决方法
    sqrt函数的实现
    O2O、C2C、B2B、B2C
    libsvm使用说明
    如何确定最适合数据集的机器学习算法
    知乎日报:她把全世界的学术期刊都黑了
    逻辑回归应用之Kaggle泰坦尼克之灾
    非均衡数据分布的分类问题
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1733061.html
Copyright © 2011-2022 走看看