WCF 回调的使用
来源:互联网 发布:网络教育的考试 编辑:程序博客网 时间:2024/06/08 08:46
你说,服务器端回调有啥用呢?这样问,估计不好回答,是吧。不急,先讨论一个情景。
假设现有服务器端S,客户端A开始连接S并调用相关操作,其中有一个操作,在功能上有些特殊,调用后无法即时回复,因为在服务器上要作一些后续,而这些处理也许会消耗一定时间,比如:
向服务器上传了一个文件,但是,为了节约空间或出于其他目的,服务器要对刚上传的文件进行处理(压缩或者多媒体文件转码),这些操作无法马上向客户端回复,而客户端也不可能就停在这里一直在等。我们希望,在客户端上传文件后马上返回,而服务器对文件处理完成后再通知一下客户端。
这样就引出一个东东——回调,E文叫Call Back。我估计用E文表述可能更好理解,Call back就是相对于Callto而言的,即调用的方向与Call to相反。
是啊,有必要解释一下,什么叫回调。我讲一个故事吧。
有一天,脑残去书店买书,之前他听别人说有一本书叫《吹牛沉思录》很好看,于是脑残也想买一本。可是,当他到书店后,东找西寻了一番,硬是没看见那本书的影子。
于是,他跑到柜台问工作人员:“我想找《吹牛沉思录》,没找到。”
工作人员马上启动书店的信息管理系统,但可以由于该系统品德不太好,居然用了35秒才启动,然后,工作人员在上面查了一下,回过头说:“抱歉,这本书太抢手了,卖完了,需要拿货。”
脑残追问:“那要啥时候有货?”
工作人员说:“大概两三天后吧,这样吧,你留个联系方式,等到货到了我再联系你。”
……
对的,这就是回调的故事。
脑残(调用方)不知道书店什么时候有货(不清楚调用的操作什么时候返回),但他总不能每天都跑去书店看看,这样太不滑算(消耗资源),于是,书店(被调用方)建议,留下联系方式(只保留内存中函数指针的地址,即回调地址),只要货到了就通知脑残(反调用)。
回调比较典型的一种就是事件,事件驱动模型以前是在VB中被大量使用,后来.NET也继承了这些优点,在此之前,C++/MFC大家都知道的,是通过消息来处理的(消息循环),其实,事件就是对消息的进一步封装,这使得应用更加简便和灵活。
在.NET中我们知道,事件其实就是一个委托,由于委托可以同时绑定多个方法的特点,故被选为事件的表现类型,估计是这样的。
比如,我们常用的,为按钮的Click事件定义一个处理。
button.Click += new EventHandler(onClick)
这样,事件Click的订阅者就是onClick方法,所谓订阅事件,就像我们平时订阅XX杂志一样,只要有新一期发布就发快递给你,你不用天天打电话去杂志社问。
onClick并不是每一刻都去问button:“你被Click了吗?”,onClick就像一个报警系统,只要特定的事件发生,它就会报警。这就是一种回调,onClick不必主动去调用button,只要处于监听状态即可,只要button被Click,onClick就会执行,不用你去调用它。
讲了这么多,不知道各位理解了没?
在WCF中使用回调,只需要多定义一个接口即可,这个接口的方法和服务协定一样,要附加OperationContractAttribu
然后在定义服务类时,在ServiceContractAttribute
在服务操作中,通过OperationContext的GetCallbackChannel方法取出回调协定的实例,调用回调的方法,就会在客户端寻找回调接口的实现类并调用对应的成员。
这样说显然不好理解,还是实践出真知。我们来做一个选号程序:
第一步,定义一个回调接口
- public
interface ICallback - {
-
// 回调操作也必须One Way -
[OperationContract(IsOneWay = true)] -
void CallClient( intv); - }
第二步,定义服务协定。
- [ServiceContract(Namespace
= "MyNamespace", -
CallbackContract = typeof(ICallback), -
SessionMode = SessionMode.Required -
)] - public
interface IService - {
-
// 会话从调用该操作启动 -
[OperationContract(IsOneWay = true, -
IsInitiating = true, -
IsTerminating = false)] -
void CallServerOp(); -
-
// 调用该操作后,会话结束 -
[OperationContract(IsOneWay = true, -
IsTerminating = true, -
IsInitiating = false)] -
void End(); - }
CallbackContract属性指向ICallback的Type。因为我要使用计时器每隔3秒钟生成一个随机数,并回调到客户端,故要启用会话。
第三步,实现服务协定。
- public
class MyService : IService,IDisposable - {
-
private ICallback m_cb; -
private Timer null;//计时器,定时干活timer = -
Random rand = null;//生成随机整数 -
-
public void CallServerOp() -
{ -
this.m_cb = OperationContext.Current.GetCallbackChannel(); -
rand = new Random(); -
// 生成随整数,并回调到客户端 -
// 每隔3秒生成一次 -
timer = new Timer((obj) null,=> m_cb.CallClient(rand.Next()), 10, 3000); -
-
} -
-
public void Dispose() -
{ -
timer.Dispose(); -
Console.WriteLine("{0} - ,服务实例已释放。" DateTime.Now.ToLongTimeString()); -
} -
-
-
public void End() //结束 -
{ -
Console.WriteLine("会话即将结束。"); -
} - }
第四步,完成服务器端的配置。
- static
void Main( string[]args) - {
-
Console.Title = "WCF服务端"; -
// 服务器基址 -
Uri baseAddress = new Uri( "http://localhost:1378/services"); -
// 声明服务器主机 -
using (ServiceHost newhost = ServiceHost( typeof(MyService),baseAddress)) -
{ -
// 添加绑定和终结点 -
// tcp绑定支持会话 -
NetTcpBinding binding = new NetTcpBinding(); -
binding.Security.Mode = SecurityMode.None; -
host.AddServiceEndpoint(typeof(IService), binding, "net.tcp://localhost:1211/rr"); -
// 添加服务描述 -
host.Description.Behaviors.Add(new ServiceMetadataBehavior true{ HttpGetEnabled = }); -
try -
{ -
// 打开服务 -
host.Open(); -
Console.WriteLine("服务已启动。"); -
} -
catch (Exception ex) -
{ -
Console.WriteLine(ex.Message); -
} -
Console.ReadKey(); -
} - }
既支持会话,传输速度又快的,非TCP莫属了,所以这里我选择NetTcpBinding,这样在默认行为下,每启动一个会话就创建一个服务实例,而当会话结束时就会释放。
======================================================================================
服务器端完工后,下面就是客户端。
第一步,新建一个Windows窗体应用项目(Windows Forms)。
第二步,到对应目录以管理员身份运行服务器端,然后在客户端添加服务引用。
第三步,在客户端实现回调接口
- public
class MyCallback : WS.IServiceCallback - {
-
// 因为该方法是由服务器调用的 -
// 如果希望在客户端能即时作出响应 -
// 应当使用事件 -
public void CallClient( intv) -
{ -
if ( this.ValueCallbacked!= null) -
{ -
this.ValueCallbacked(this, v); -
} -
} -
/// -
/// 回调引发该事件 -
/// -
public event EventHandler<</SPAN>int> ValueCallbacked; - }
注意,回调的接口是在客户端实现的,不是服务器端。
第四步,设计窗口。
- using
System; - using
System.Collections.Generic; - using
System.ComponentModel; - using
System.Data; - using
System.Drawing; - using
System.Linq; - using
System.Text; - using
System.Threading.Tasks; - using
System.Windows.Forms; -
- namespace
Client - {
-
public partial classForm1 : Form -
{ -
WS.ServiceClient cl = null; -
MyCallback cb = null; -
public Form1() -
{ -
InitializeComponent(); -
cb = new MyCallback(); -
cb.ValueCallbacked += cb_ValueCallbacked; -
-
} -
-
void cb_ValueCallbacked( objectsender, inte) -
{ -
this.lbResult.Text = e.ToString(); -
} -
-
private void button1_Click( objectsender, EventArgs e) -
{ -
cl = new WS.ServiceClient( newSystem.ServiceModel.InstanceContext(cb)); -
cl.CallServerOp(); -
button1.Enabled = false; -
button2.Enabled = true; -
} -
-
private void button2_Click( objectsender, EventArgs e) -
{ -
cl.End(); -
button1.Enabled = true; -
button2.Enabled = false; -
} -
} - }
======================================================================================现在来测试一下吧。
转自:http://blog.csdn.net/tcjiaan/article/details/8298486
- WCF 回调的使用
- WCF 回调原理
- 我的windows mobile WCF项目
- Wcf的简单使用
- Wcf的使用
- WCF的使用方式
- WCF的回调操作
- ZBar的使用
- 高德地图 MAMapKit 的使用
- WCF 分布式事务的使用
- jquery easyui datebox 的使用 .
- 使用WCF 测试客户端测试你的WCF服务
- WCF系列博文(一)-----使用WCF的好处
- WCF使用入门(一)【基于双工通信的WCF应用】
- 使用oracle 的闪回功能
- merge 的使用
- @property 的使用
- JMenu 的使用
- C# 串口操作系列(2) --&…
- WCF客户端配置文件(参考)
- 关于WCF操作重载的个人总结
- 关于WCF契约继承中层级关系在客户…
- WCF开发之服务契约
- WCF 回调的使用
- WCF 回调原理
- 有时候真想走到你面前对你来一句:fuck you mother。
- C# 事件机制
- 在连接到SQL Server2005时,在…
- SQLite3数据库操作: 建库,建…
- .Net中对Sqlite数据库操作封装类
- ORM框架类型自动转换原理
- Access2003 数据库中关于时间…