博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Silverlight与WCF通信(三) :Silverlight与IIS宿主的WCF间的双工通信
阅读量:6694 次
发布时间:2019-06-25

本文共 5972 字,大约阅读时间需要 19 分钟。

     最近项目比较忙,这第三篇更新的比较晚,今日补上。今天我们来演示一下Silverlight与WCF的双工通信,所谓的双工顾名思义就是双方之间均可以向对方发送消息,但是WCF中的双工并不和传统的基于TCP协议的双工通信是一样的,WCF的双工是客户端调用WCF服务的时候,附加一个回调对象,服务端执行服务的时候,通过这个回调对象回调客户端的操作,说白了就是 你调用我一下,我回调你一下,来实现的双工通信。

     WCF的双工通信我们这次演示的是订阅-发布模式,大家也可以这么理解,多个客户端调用订阅服务后,服务器端推送数据给客户端,我们来设想这样一个案例场景:“服务器端监视一些设备的运行状态,当设备有故障之后,客户端要将告警的设备显示出来”,实现起来并不难,客户端通过定时请求服务器端的告警数据就可以实现,但是这种定时刷新服务器端的做法对服务器端压力是很大的,不是一个明智选择,下面来演示这个Demo,实现服务器端推送告警数据给客户端。

项目结构

    项目结构和上两篇是一样的,简单说明一下:

    LxContract程序集:WCF 的数据契约和操作契约    

    LxService  程序集:WCF操作契约的实现

    LxWCF_web:发布WCF的网站

    SilverlightDuplex:Silverlight应用程序,也就是该客户端调用WCF服务

代码实现

类库LxContract:(包括数据契约Alarm.cs;操作契约IAlarmSrv.cs;回调契约IAlarmCallBack.cs)

Alarm.cs 代码
using System;using System.Runtime.Serialization;namespace LxContract{    [DataContract]    public class Alarm    {        ///         /// 设备的编号        ///         [DataMember]        public string DeviceNo { get; set; }        ///         ///告警时间        ///         [DataMember]        public DateTime AlarmTime { get; set; }    }}
IAlarmCallBack.cs 代码
using System.ServiceModel;namespace LxContract{    public interface IAlarmCallBack    {        [OperationContract(IsOneWay = true)]        void ReceiveAlarmData(Alarm alarm);    }}
IAlarmSrv.cs 代码
using System.ServiceModel;namespace LxContract{    [ServiceContract(CallbackContract = typeof(IAlarmCallBack))]    public interface IAlarmSrv    {        [OperationContract]        string RequestAlarmData();    }}

[ServiceContract(CallbackContract = typeof(IAlarmCallBack))]  服务端对客户端进行回调其实就是调用寄宿在客户端的代理中的ReceiveAlarmData方法,因此我们要利用 SeviceContract中的CallBackContract属性来指定是哪个回调契约。

类库LxService:(该类库仅包括AlarmService.cs文件,AlarmService用来实现IAlarmSrv契约的具体操作)

AlarmService.cs
using System;using LxContract;using System.ServiceModel;namespace LxService{    public class AlarmService : IAlarmSrv    {        System.Timers.Timer timer;        IAlarmCallBack client;        public string RequestAlarmData()        {            string ret = string.Format("当前时间:{0},服务器将每隔3秒钟返回一条告警数据", DateTime.Now);            //这里获取当前的客户端            //可以定义一个List 来保存所有的客户端            client = OperationContext.Current.GetCallbackChannel
(); timer = new System.Timers.Timer(); timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed); timer.Interval = 3000; timer.Start(); return ret; } void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { //这里可修改成获取真实设备数据的方法 //本实例定时返回一个设备 Alarm alarm = new Alarm() { DeviceNo = Guid.NewGuid().ToString(), AlarmTime = DateTime.Now }; client.ReceiveAlarmData(alarm); } }}

站点LxWcf_Web :

 同样是一个空的Asp.net 网站,需要添加引用LxContranc和LxService两个类库,并添加一个wcf服务文件命名为DuplexSrv.svc,用于进行服务的发布,对其鼠标右击选择查看标记,将代码修改为:

<%@ ServiceHost Language="C#" Debug="true" Service="LxService.AlarmService" %>

由于我们还采用IIS宿主改网站,信道依然采用netTcp方式,因此对Web.config文件中配置如下:

Web.config 配置

本次我们还利用第二篇介绍的IIS宿主netTcp绑定方式WCF的方法部署该网站,这里就不再进行贴图和说明了,具体参见

SilverlightDuplex 客户端

由于我们已经成功在IIS中配置好了LxWcf_Web 这个发布WCF的站点,我们可以在Silverlight项目中添加服务引用,就可以找到此服务,命名为Wcf.Duplex。

MainPage.xaml 布局代码:
MainPage.xaml.cs 代码
using System;using System.Windows;using System.Windows.Controls;using System.Collections.ObjectModel;using SilverlightDuplex.Wcf.Duplex;namespace SilverlightDuplex{    public partial class MainPage : UserControl    {        ObservableCollection
listAlarm = null; public MainPage() { InitializeComponent(); listAlarm = new ObservableCollection
(); this.btnOk.Click += new RoutedEventHandler(btnOk_Click); this.Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { this.dgAlarm.ItemsSource = listAlarm; } void btnOk_Click(object sender, RoutedEventArgs e) { AlarmSrvClient proxyclient = new AlarmSrvClient(); proxyclient.RequestAlarmDataCompleted += new EventHandler
(proxyclient_RequestAlarmDataCompleted); proxyclient.ReceiveAlarmDataReceived += new EventHandler
(proxyclient_ReceiveAlarmDataReceived); proxyclient.RequestAlarmDataAsync(); } //服务器端回调获取告警完成 void proxyclient_ReceiveAlarmDataReceived(object sender, ReceiveAlarmDataReceivedEventArgs e) { if (e.Error == null) { listAlarm.Add(e.alarm); } } //请求获取告警数据完成 void proxyclient_RequestAlarmDataCompleted(object sender, RequestAlarmDataCompletedEventArgs e) { if (e.Error == null) { this.tbInfo.Text = e.Result.ToString(); } } }}

 

至此代码编写完毕,我们来运行一下Silverlight客户端,右击该项目--调试--启动新实例,Silverlight程序运行起来之后,点击获取告警数据按钮,我们就会发现服务器端每隔3秒中给该客户端下发一条告警数据。

补充一点:回调契约中的[OperationContract(IsOneWay = true)] 有什么用呢? 这是防止调用wcf产生回调死锁异常的一种解决方法,还有一种解决方法就是对服务的行为进行设定,可以为类AlarmService增加

[ServiceBehavior(ConcurrencyMode=ConcurrencyMode.Reentrant)]来解决死锁的问题。不过在Silverlight中貌似只能用[OperationContract(IsOneWay = true)],否则在添加引用后,生成的时候就会发生错误。

转载于:https://www.cnblogs.com/lxblog/archive/2012/08/01/2618326.html

你可能感兴趣的文章
USB驱动
查看>>
使用异步 I/O 大大提高应用程序的性能
查看>>
代码与画画,
查看>>
计算器
查看>>
RK3399 tensorflow (python3.5)非编译安装记
查看>>
交换机端口
查看>>
EntityFramework-DBFirst-重新生成后写的验证消失(解决办法)
查看>>
android 体系结构
查看>>
PHP异步:在PHP中使用 fsockopen curl 实现类似异步处理的功能
查看>>
又到一年双十一
查看>>
【HDOJ】1716 排列2
查看>>
【HDOJ】3400 Line belt
查看>>
【HDOJ】3832 Earth Hour
查看>>
寒假学习计划
查看>>
Android内存小谈
查看>>
JVM Guide
查看>>
大数模版
查看>>
HDU4044 GeoDefense(树形dp+分组背包)
查看>>
Microsoft .Net Remoting系列专题之三:Remoting事件处理全接触
查看>>
JavaScript常用标签和方法总结
查看>>