• 一步一步学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地址后面跟上随机数,是因为可能在一个机器上会打开多个客户端,需要在这个时候能在服务器端区分多个客户端。

     

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

  • 相关阅读:
    文件方式实现完整的英文词频统计实例
    组合数据类型练习,英文词频统计实例上
    英文词频统计预备,组合数据类型练习
    凯撒密码、GDP格式化输出、99乘法表
    字符串基本操作
    datetime处理日期和时间
    中文词频统计
    文件方式实现完整的英文词频统计实例
    组合数据类型练习,英文词频统计实例上
    英文词频统计预备,组合数据类型练习
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1733061.html
Copyright © 2020-2023  润新知