一步一步学Remoting之六:事件(2)
到了午休的时间,抓紧时间继续写,上次说有2个遗留问题:
(1)关闭一个客户端以后会影响其他的客户端事件
原因:客户端没有取消事件订阅就关闭了,触发事件的时候找不到事件订阅者
解决:遍历委托链,找到异常的对象,从委托链中卸下
(2)服务器端对客户端广播,客户端能收到其他客户端的事件处理信息
原因:使用了Singleton模式,共享远程对象
解决:因为需要远程对象有状态且不共享实例,所以只有客户端激活可以选择
修改后的服务端:
修改后的远程对象:
修改后的客户端:
到了午休的时间,抓紧时间继续写,上次说有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.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 + " % " );
}
}
}
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( " 主线程方法结束 " );
}
}
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地址后面跟上随机数,是因为可能在一个机器上会打开多个客户端,需要在这个时候能在服务器端区分多个客户端。
备注:我的所有例子都是在客户端和服务器端部署远程对象的,其实这个做法不是很好,我们应该仅仅把接口部署在两地,远程对象仅仅部署在服务器端即可。
本文转自温景良(Jason)博客园博客,原文链接:http://www.cnblogs.com/wenjl520/archive/2009/08/08/1541955.html,如需转载请自行联系原作者
原文地址:http://www.cnblogs.com/lovecherry/archive/2005/05/23/160954.ht