原因:客户端没有取消事件订阅就关闭了,触发事件的时候找不到事件订阅者
解决:遍历委托链,找到异常的对象,从委托链中卸下
(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地址后面跟上随机数,是因为可能在一个机器上会打开多个客户端,需要在这个时候能在服务器端区分多个客户端。

备注:我的所有例子都是在客户端和服务器端部署远程对象的,其实这个做法不是很好,我们应该仅仅把接口部署在两地,远程对象仅仅部署在服务器端即可。
文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!




