zoukankan
html css js c++ java
[Remoting专题系列] 十一:事件 【转】
在 Remoting 中使用 Event 主要是为了实现 CallBack 机制,让服务器在接收到某个
"
消息
"
时,主动调用某个或多个客户端的方法。
我们先看一个例子。
using
System;
using
System.Collections;
using
System.Collections.Generic;
using
System.Reflection;
using
System.Runtime.Serialization.Formatters;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;
namespace
Learn.Library.Remoting
{
/**/
///
<summary>
///
委托类型
///
</summary>
public
delegate
void
TestHandler();
/**/
///
<summary>
///
远程类型
///
</summary>
public
class
Data : MarshalByRefObject
{
public
TestHandler OnTest;
public
void
Test()
{
Console.WriteLine(
"
Test
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
if
(OnTest
!=
null
) OnTest();
}
}
public
class
RemotingTest2
{
/**/
///
<summary>
///
服务器端代码
///
</summary>
static
void
Server()
{
AppDomain server
=
AppDomain.CreateDomain(
"
server
"
);
server.DoCallBack(
delegate
{
BinaryServerFormatterSinkProvider bin
=
new
BinaryServerFormatterSinkProvider();
bin.TypeFilterLevel
=
TypeFilterLevel.Full;
TcpServerChannel channel
=
new
TcpServerChannel(
"
server
"
,
801
, bin);
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof
(Data),
"
data
"
,
WellKnownObjectMode.Singleton);
}
);
}
/**/
///
<summary>
///
客户端代码
///
</summary>
static
void
Client()
{
TcpClientChannel channel
=
new
TcpClientChannel();
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownClientType(
typeof
(Data),
"
tcp://localhost:801/data
"
);
Data data
=
new
Data();
data.OnTest
+=
delegate
{
Console.WriteLine(
"
OnTest
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
}
;
data.Test();
}
static
void
Main()
{
Server();
Client();
}
}
}
输出:
Test
(AppDomain:server)
OnTest
(AppDomain:server)
运行结果表明客户端事件方法 OnTest 被顺利执行。只不过结果有点问题,OnTest 是在服务器程序域内执行,这显然和我们设想服务器去通知客户端有所出入。这种方式实质上是将客户端委托方法一起序列化为消息传递到服务器端,然后在服务器应用程序域被执行,因此客户端是无法接收到所谓
"
回调消息
"
的。
要实现我们所需要的 Remoting Event,需要做如下步骤:
1
. 采取所谓 Duplex 方式。也就是说在客户端和服务器同时启用 ServerChannel 和 ClientChannel,因此我们需要使用 HttpChannel 或 TcpChannel。
2
. 客户端事件方法应该是一个继承自 MarshalByRefObject 类型的实例方法。因为服务器是通过创建客户端的 MBR SAO 对象来实现回调的。
3
. 缺省情况下,Delegate 无法被序列化,因此我们需要将服务器的 Formatter.TypeFilterLevel 设置为 Full。
修改后的代码。
using
System;
using
System.Collections;
using
System.Collections.Generic;
using
System.Reflection;
using
System.Runtime.Serialization.Formatters;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;
namespace
Learn.Library.Remoting
{
/**/
///
<summary>
///
委托类型
///
</summary>
public
delegate
void
TestHandler();
/**/
///
<summary>
///
远程类型
///
</summary>
public
class
Data : MarshalByRefObject
{
public
TestHandler OnTest;
public
void
Test()
{
Console.WriteLine(
"
Test
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
if
(OnTest
!=
null
) OnTest();
}
}
/**/
///
<summary>
///
客户端远程类型
///
</summary>
public
class
ClientData : MarshalByRefObject
{
public
void
OnTestMethod()
{
Console.WriteLine(
"
Test
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
}
}
public
class
RemotingTest2
{
/**/
///
<summary>
///
服务器端代码
///
</summary>
static
void
Server()
{
AppDomain server
=
AppDomain.CreateDomain(
"
server
"
);
server.DoCallBack(
delegate
{
BinaryClientFormatterSinkProvider cbin
=
new
BinaryClientFormatterSinkProvider();
BinaryServerFormatterSinkProvider sbin
=
new
BinaryServerFormatterSinkProvider();
sbin.TypeFilterLevel
=
TypeFilterLevel.Full;
Hashtable properties
=
new
Hashtable();
properties[
"
port
"
]
=
801
;
TcpChannel channel
=
new
TcpChannel(properties, cbin, sbin);
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof
(Data),
"
data
"
,
WellKnownObjectMode.Singleton);
}
);
}
/**/
///
<summary>
///
客户端代码
///
</summary>
static
void
Client()
{
TcpChannel channel
=
new
TcpChannel(
802
);
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownClientType(
typeof
(Data),
"
tcp://localhost:801/data
"
);
Data data
=
new
Data();
data.OnTest
+=
new
ClientData().OnTestMethod;
data.Test();
}
static
void
Main()
{
Server();
Client();
}
}
}
查看全文
相关阅读:
Windows 下安装 Python + Django
asp.net core 一个中小型项目实战的起手式——Swagger配置
asp.net core 一个中小型项目实战的起手式——项目搭建与仓储模式下的持久层创建(1)
c#一些常用知识点
ADO.NET中的5个主要对象
JavaScript的闭包特性如何给循环中的对象添加事件(一)
在什么情况下会用到虚方法?它与接口有什么不同?
一般处理程序Session
什么是code-Behind技术?
什么是事务?
原文地址:https://www.cnblogs.com/cxd4321/p/888804.html
最新文章
C# 队列(Queue) 和堆栈(Stack)
Jquery 保留N位小数,且千位以上用","号隔开
数据库导入.bacpac 文件创建新实例
Ajax 请求下载 Execl 文件
Asp.net MVC + Signalr 实现多人聊天室
读取Execl表数据 导入数据库
从新手小白到老手大白的心路历程-First Blog
从新手小白到老手大白的成长之路第二弹-WPF之UI界面之Grid面板
NetCore踩坑记2、喜!悲?项目演进的分享和EntityFrameworkCore升级之后的奇怪现象
NetCore踩坑记1、 一块网卡引发的血案
热门文章
使用脚本将AspNetCore发布到IIS上
dotnet Core 图片验证码
Visual Studio 2019激活
CentOS7+Docker+MangoDB下部署简单的MongoDB分片集群
Java同C#的语法不同之处
模糊查询库的存储过程(SQLServer)
C#工具类SqlServerHelper,基于System.Data.SqlClient封装
C#工具类MySqlHelper,基于MySql.Data.MySqlClient封装
C#工具类OracleHelper,基于Oracle.ManagedDataAccess.Client封装
关于 .Net Core runtimeconfig 文件说明
Copyright © 2011-2022 走看看