silverlightwcf:Silverlight(23) - 2.0通信的调用WCF的双向通信(Duplex Service)

  本文源代码下载地址:

  http://flashview.ddvip.com/2008_12/Silverlight.rar

  介绍

  Silverlight 2.0 WCF 双向通信服务(Duplex Service) 开发个服务端主动向客服端发送股票信息首先客户端先向服务端发送需要监控股票股票代码然后服务端在该股信息发生变化时候将信息推送到客户端

  服务端:

  定义服务契约及回调接口

  从当前上下文获取回调客户端信道

  需要话则向客户端信道“推”消息

  客户端:

  构造 PollingDuplexHttpBinding 并在其上创建 IDuplexSessionChannel 信道工厂

  异步方式打开信道工厂

  异步方式打开信道

  构造需要发送到服务端消息 .ServiceModel.Channels.Message

  异步向服务端发送消息

  监听指定信道用于异步方式接收服务端返回消息

  不需要再接收服务端消息则关闭信道

  举例

  服务端:

  IDuplexService.cs

using ;
using .Collections.Generic;
using .Linq;
using .Runtime.Serialization;
using .ServiceModel;
using .Text;
  
using .ServiceModel.Channels;
  
/**//// <summary>
/// IDuplexService - 双工(Duplex)服务契约
/// CallbackContract - 双工(Duplex)服务回调类型
/// </summary>
[ServiceContract(Namespace = "Silverlight20", CallbackContract = typeof(IDuplexClient))]
public erface IDuplexService
{
  /**//// <summary>
  /// 客户端向服务端发送消息思路方法
  /// </summary>
  /// <param name="receivedMessage">客户端向服务端发送消息 .ServiceModel.Channels.Message</param>
  [OperationContract(IsOneWay = true)]
  void SendStockCode(Message receivedMessage);
}
  
/**//// <summary>
/// 双工(Duplex)服务回调接口
/// </summary>
public erface IDuplexClient
{
  /**//// <summary>
  /// 客户端接收服务端发送过来消息思路方法
  /// </summary>
  /// <param name="Message">服务端向客户端发送消息 .ServiceModel.Channels.Message</param>
  [OperationContract(IsOneWay = true)]
  void ReceiveStockMessage(Message Message);
}


  DuplexService.cs

using ;
using .Collections.Generic;
using .Linq;
using .Runtime.Serialization;
using .ServiceModel;
using .Text;
  
using .ServiceModel.Channels;
using .Threading;
using .ServiceModel.Activation;
using .IO;
  
/**//// <summary>
/// Duplex 服务服务端实现
/// 本文以客户端向服务端提交股票代码服务端定时向客户端发送股票信息为例
/// </summary>
public DuplexService : IDuplexService
{
  IDuplexClient _client;
  bool _status = true;
  
  /**//// <summary>
  /// 客户端向服务端发送股票代码思路方法
  /// </summary>
  /// <param name="receivedMessage">包含股票代码 .ServiceModel.Channels.Message </param>
  public void SendStockCode(Message receivedMessage)
  {
    // 获取当前上下文回调信道
    _client = OperationContext.Current.GetCallbackChannel<IDuplexClient>;
  
    // 如果发生则不再执行
    OperationContext.Current.Channel.Faulted EventHandler(delegate { _status = false; });
  
    // 获取用户提交股票代码
     stockCode = receivedMessage.GetBody<>;
  
    // 每3秒向客户端发送次股票信息
    while (_status)
    {
      // 构造需要发送到客户端 .ServiceModel.Channels.Message
      // Duplex 服务仅支持 Soap11 Action 为请求地(需要执行某行为路径)
      Message stockMessage = Message.CreateMessage(
        MessageVersion.Soap11,
        "Silverlight20/IDuplexService/ReceiveStockMessage",
        .Format("StockCode: {0}; StockPrice: {1}; CurrentTime: {2}",
          stockCode,
           Random.Next(1, 200),
          DateTime.Now.));
  
      try
      {
        // 向客户端“推”数据
        _client.ReceiveStockMessage(stockMessage);
      }
      catch (Exception ex)
      {
        // 出错则记日志
        using (StreamWriter sw = StreamWriter(@"C:Silverlight_Duplex_Log.txt", true))
        {
          sw.Write(ex.);
          sw.WriteLine;
        }
      }
  
      .Threading.Thread.Sleep(3000);
    }
  }
}


  PollingDuplexServiceHostFactory.cs

using ;
using .Collections.Generic;
using .Linq;
using .Web;
  
using .ServiceModel;
using .ServiceModel.Channels;
using .ServiceModel.Activation;
  
/**//* 以下部分摘自文档 */
  
// 服务 svc 文件 Factory 要指定为此类
public PollingDuplexServiceHostFactory : ServiceHostFactoryBase
{
  public override ServiceHostBase CreateServiceHost( constructorString,
    Uri baseAddresses)
  {
     PollingDuplexSimplexServiceHost(baseAddresses);
  }
}
  
PollingDuplexSimplexServiceHost : ServiceHost
{
  public PollingDuplexSimplexServiceHost(params .Uri addresses)
  {
    base.InitializeDescription(typeof(DuplexService), UriSchemeKeyedCollection(addresses));
  }
  
  protected override void InitializeRuntime
  {
    // 配置 WCF 服务和 Silverlight 客户端的间 Duplex 通信
    // Silverlight 客户端定期轮询网络层上服务并检查回调信道上由服务端发送所有新消息
    // 该服务会将回调信道上由服务端发送所有消息进行排队并在客户端轮询服务时将这些消息传递到该客户端
  
    PollingDuplexBindingElement pdbe = PollingDuplexBindingElement
    {
      // ServerPollTimeout - 轮询超时时间
      // InactivityTimeout - 服务端和客户端在此超时时间内无任何消息交换情况下服务会关闭其会话
  
      ServerPollTimeout = TimeSpan.FromSeconds(3),
      InactivityTimeout = TimeSpan.FromMinutes(1)
    };
  
    // 为服务契约(service contract)添加个终结点(endpo)
    // Duplex 服务仅支持 Soap11
    this.AddServiceEndpo(
      typeof(IDuplexService),
       CustomBinding(
        pdbe,
         TextMessageEncodingBindingElement(
          MessageVersion.Soap11,
          .Text.Encoding.UTF8),
         HttpTransportBindingElement),
        "");
  
    base.InitializeRuntime;
  }
}


  DuplexService.svc

<%@ ServiceHost Language="C#" Debug="true" Service="DuplexService" CodeBehind="~/App_Code/DuplexService.cs" Factory="PollingDuplexServiceHostFactory" %>

  客户端:

  DuplexService.xaml

<UserControl x:Class="Silverlight20.Communication.DuplexService"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <StackPanel HorizontalAlignment="Left" Margin="5">
  
    <TextBox x:Name="txtStockCode" Text="请输入股票代码" Margin="5" />
    <Button x:Name="btnSubmit" Content="获取股票信息" Click="btnSubmit_Click" Margin="5" />
    <Button x:Name="btnStop" Content="停止获取" Click="btnStop_Click" Margin="5" />
    <TextBlock x:Name="lblStockMessage" Margin="5" />
  
  </StackPanel>
</UserControl>


  DuplexService.xaml.cs

using ;
using .Collections.Generic;
using .Linq;
using .Net;
using .Windows;
using .Windows.Controls;
using .Windows.Documents;
using .Windows.Input;
using .Windows.Media;
using .Windows.Media.Animation;
using .Windows.Shapes;
  
using .ServiceModel;
using .ServiceModel.Channels;
using .Threading;
using .IO;
  
Silverlight20.Communication
{
  public partial DuplexService : UserControl
  {
    SynchronizationContext _syncContext;
  
    // 是否接收服务端发送过来消息
    bool _status = true;
  
    public DuplexService
    {
      InitializeComponent;
    }
  
    private void btnSubmit_Click(object sender, RoutedEventArgs e)
    {
      _status = true;
  
      // UI 线程
      _syncContext = SynchronizationContext.Current;
  
      PollingDuplexHttpBinding binding = PollingDuplexHttpBinding
      {
        // InactivityTimeout - 服务端和客户端在此超时时间内无任何消息交换情况下服务会关闭其会话
        InactivityTimeout = TimeSpan.FromMinutes(1)
      };
  
      // 构造 IDuplexSessionChannel 信道工厂
      IChannelFactory<IDuplexSessionChannel> factory =
        binding.BuildChannelFactory<IDuplexSessionChannel>( BindingParameterCollection);
  
      // 打开信道工厂
      IAsyncResult factoryOpenResult =
        factory.BeginOpen( AsyncCallback(OnOpenCompleteFactory), factory);
  
       (factoryOpenResult.CompletedSynchronously)
      {
        // 如果信道工厂被打开这个 异步操作 已经被 同步完成 则执行下
        CompleteOpenFactory(factoryOpenResult);
      }
    }
  
    private void btnStop_Click(object sender, RoutedEventArgs e)
    {
      _status = false;
    }
  
    void _disibledevent= ()text;
    }
  }
}


Tags:  silverlight.2.0 silverlight是什么 silverlight silverlightwcf

延伸阅读

最新评论

发表评论