本文参考自http://www.cnblogs.com/wangweimutou/p/4409227.html,纯属读书笔记,加深记忆

一、简介

在前面的随笔中,详细的介绍了WCF客户端服务的调用方法,但是那些操作全都是同步的,所以我们需要很长的时间等待服务器的反馈,如何一台服务器的速度很慢,所以客户端得到结果就需要很长的时间,试想一下,如果客户端是个web项目,那么客户体验可想而知,所以为了不影响后续代码执行和用户的体验,就需要使用异步的方式来调用服务。注意这里的异步是完全针对客户端而言的,与WCF服务契约的方法是否异步无关,也就是在不改变操作契约的情况下,我们可以用同步或者异步的方式调用WCF服务。

二、操作示例

1、WCF服务层搭建:新建契约层、服务层、和WCF宿主,添加必须的引用(这里不会的参考本人前面的随笔),配置宿主,生成解决方案,打开Host.exe,开启服务。具体的代码如下:

ICalculate.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.ServiceModel;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7.  
  8. namespace IService
  9. {
  10. [ServiceContract]
  11. public interface ICalculate
  12. {
  13. [OperationContract]
  14. int Add(int a, int b);
  15. }
  16. }

IUserInfo.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Runtime.Serialization;
  5. using System.ServiceModel;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8.  
  9. namespace IService
  10. {
  11. [ServiceContract]
  12. public interface IUserInfo
  13. {
  14. [OperationContract]
  15. User[] GetInfo(int? id);
  16. }
  17.  
  18. [DataContract]
  19. public class User
  20. {
  21. [DataMember]
  22. public int ID { get; set; }
  23. [DataMember]
  24. public string Name { get; set; }
  25. [DataMember]
  26. public int Age { get; set; }
  27. [DataMember]
  28. public string Nationality { get; set; }
  29. }
  30. }

注:必须引入System.Runtime.Serialization命名空间,应为User类在被传输时必须是可序列化的,否则将无法传输

Calculate.cs

  1. using IService;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7.  
  8. namespace Service
  9. {
  10. public class Calculate : ICalculate
  11. {
  12. public int Add(int a, int b)
  13. {
  14. return a + b;
  15. }
  16. }
  17. }

UserInfo.cs

  1. using IService;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7.  
  8. namespace Service
  9. {
  10. public class UserInfo : IUserInfo
  11. {
  12. public User[] GetInfo(int? id)
  13. {
  14. List<User> Users = new List<User>();
  15. Users.Add(new User { ID = 1, Name = "张三", Age = 11, Nationality = "China" });
  16. Users.Add(new User { ID = 2, Name = "李四", Age = 12, Nationality = "English" });
  17. Users.Add(new User { ID = 3, Name = "王五", Age = 13, Nationality = "American" });
  18.  
  19. if (id != null)
  20. {
  21. return Users.Where(x => x.ID == id).ToArray();
  22. }
  23. else
  24. {
  25. return Users.ToArray();
  26. }
  27. }
  28. }
  29. }

Program.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using Service;
  6. using System.ServiceModel;
  7.  
  8. namespace Host
  9. {
  10. class Program
  11. {
  12. static void Main(string[] args)
  13. {
  14. using (ServiceHost host = new ServiceHost(typeof(Calculate)))
  15. {
  16. host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
  17. host.Open();
  18. Console.Read();
  19. }
  20. }
  21. }
  22. }

App.Config

  1. <?xml version="1.0"?>
  2. <configuration>
  3. <system.serviceModel>
  4.  
  5. <services>
  6. <service name="Service.Calculate" behaviorConfiguration="mexBehavior">
  7. <host>
  8. <baseAddresses>
  9. <add baseAddress="http://localhost:1234/Calculate/"/>
  10. </baseAddresses>
  11. </host>
  12. <endpoint address="" binding="wsHttpBinding" contract="IService.ICalculate" />
  13. <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  14. </service>
  15. </services>
  16.  
  17. <behaviors>
  18. <serviceBehaviors>
  19. <behavior name="mexBehavior">
  20. <serviceMetadata httpGetEnabled="true"/>
  21. <serviceDebug includeExceptionDetailInFaults="true"/>
  22. </behavior>
  23. </serviceBehaviors>
  24. </behaviors>
  25. </system.serviceModel>
  26. </configuration>

ok,打开Host.exe

服务开启成功!

2、新建名为Client的客户端控制台程序,通过添加引用的方式,异步调用WCF服务

添加添加对服务终结点地址http://localhost:6666/UserInfo/的引用,设置服务命名空间为UserInfoServiceNS,点击高级设置,勾选生成异步操作选项,生成客户端代理类和配置文件代码后,完成Client对服务的调用.

ok,开始编写program.cs代码:

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Client.UserInfoServiceNS;
  7.  
  8. namespace Client
  9. {
  10. class Program
  11. {
  12. static void Main(string[] args)
  13. {
  14. UserInfoClient proxy = new UserInfoClient();
  15. proxy.GetInfoCompleted += new EventHandler<GetInfoCompletedEventArgs>(proxy_GetInfoCompleted);//注册proxy_GetInfoCompleted到proxy.GetInfoCompleted中
  16. proxy.GetInfoAsync(null);//开始异步调用
  17. Console.WriteLine("此字符串在调用方法前输出,说明异步调用成功!");
  18. Console.Read();
  19. }
  20.  
  21. static void proxy_GetInfoCompleted(object sender, GetInfoCompletedEventArgs e)
  22. {
  23. User[] Users = e.Result.ToArray();
  24. Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality");
  25. for (int i = ; i < Users.Length; i++)
  26. {
  27. Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
  28. Users[i].ID.ToString(),
  29. Users[i].Name.ToString(),
  30. Users[i].Age.ToString(),
  31. Users[i].Nationality.ToString());
  32. }
  33. }
  34. }
  35. }

从上面的代码可以看出WCF服务端和WCF客户端采用了事件驱动机制,也就是所谓的发布-订阅模式,不了解的话,请参考本人的C# 委托,当proxy.GetInfoAsync(null)从服务端获取数据成功之后,即开始执行EventHandler<T>上绑定的方法.

  1. public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);

通过参数类型TEventArgsResult可以获得返回结果

  1. User[] Users = e.Result.ToArray();

三、通过svcutil生成客户端代理类,并通过重写客户端的服务契约,完成对服务端服务的异步吊用

新建名为Client1的客户端控制台程序,通过svcutil.exe工具生成的客户端代理类,,异步调用WCF服务

(1)、打开cmd,输入cd C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin

(2)、输入svcutil.exe   /out:f:\UserInfoClient.cs  /config:f:\App.config  http://localhost:6666/UserInfo/  /a  /tcv:Version35

ok,生成成功

(5)、将生成的文件拷贝到项目中,引入System.Runtime.Serialization命名空间和System.ServiceModel命名空间

(6)、剩下的步骤和上面的一样

WCF系列教程之客户端异步调用服务的更多相关文章

  1. WCF初探-11:WCF客户端异步调用服务

    前言: 在上一篇WCF初探-10:WCF客户端调用服务 中,我详细介绍了WCF客户端调用服务的方法,但是,这些操作都是同步进行的.有时我们需要长时间处理应用程序并得到返回结果,但又不想影响程序后面代码 ...

  2. WCF入门教程(三)定义服务协定--属性标签

    WCF入门教程(三)定义服务协定--属性标签 属性标签,成为定义协议的主要方式.先将最简单的标签进行简单介绍,以了解他们的功能以及使用规则. 服务协定标识,标识哪些接口是服务协定,哪些操作时服务协定的 ...

  3. 前端测试框架Jest系列教程 -- Asynchronous(测试异步代码)

    写在前面: 在JavaScript代码中,异步运行是很常见的.当你有异步运行的代码时,Jest需要知道它测试的代码何时完成,然后才能继续进行另一个测试.Jest提供了几种方法来处理这个问题. 测试异步 ...

  4. spring cloud系列教程第八篇-修改服务名称及获取注册中心注册者的信息

    spring cloud系列教程第八篇-修改服务名称及获取注册中心注册者的信息 本文主要内容: 1:管理页面主机名及访问ip信息提示修改 2:获取当前注册中心的服务列表及每个服务对于的服务提供者列表 ...

  5. 【转】无废话WCF系列教程

    转自:http://www.cnblogs.com/iamlilinfeng/category/415833.html     看后感:这系列的作者李林峰写得真的不错,通过它的例子,让我对WCF有了一 ...

  6. WCF系列教程之初识WCF

    本随笔参考自WCF编程系列(一)初识WCF,纯属读书笔记,加深记忆. 1.简介:Windows Communication Foundation(WCF)是微软为构建面向服务的应用程序所提供的统一编程 ...

  7. Webservice客户端动态调用服务端功能方法

    一.发布WebService服务 方式一:在服务端生成wsdl文件,下方客户端直接引用即可     优点:针对要发布的方法生成一个wsdl文件即可,无需多余配置.   缺点:每次服务端方法发生改变都需 ...

  8. cxf 生成客户端代码调用服务

    cxf是另一种发布webservice的方式,与jdk提供的相比 jdk提供的是wsimport cxf 提供的是 wsdl2java- d 地址 根据http://www.cnblogs.com/f ...

  9. 通过.NET客户端异步调用Web API(C#)

    在学习Web API的基础课程 Calling a Web API From a .NET Client (C#) 中,作者介绍了如何客户端调用WEB API,并给了示例代码. 但是,那些代码并不是非 ...

随机推荐

  1. ASIHTTPRequest-Cookie的使用[转]

    ASIHTTPRequest允许你使用全局存储来和所有使用CFNetwork或者NSURLRequest接口的程序共享cookie. 如果设置useCookiePersistence为YES(默认值) ...

  2. Linux 基础教程 26-基础网络配置

    基本配置     要想上网,计算机需要有专门的网络连接设备,即网络接口卡或者网卡.网卡按照与计算机主机的连接方式可以分为PCI网卡.ISA网卡及无线网卡(USB网卡)等.在Linux中可以使用命令ls ...

  3. Baidu Map开发示例

    1.获取SHA1码 在Eclipse中点击“Windows”----->“Preferences” ----->“Android” ----->“Build”如下图: 打开“Win+ ...

  4. kali下搭建WiFi钓鱼热点

    在linux下建立无线热点并不像在windows下开启网络共享或者使用无线网卡驱动设置AP模式即可. linux下的无线共享要用到两个软件:hostapd(创建无线热点).dnsmasq(dns服务和 ...

  5. After Upgrade To Release 12.1.3 Users Receive "Function Not Available To This Responsibility" Error While Selecting Sub Menus Under Diagnostics (Doc ID 1200743.1)

    APPLIES TO: Oracle Application Object Library - Version 12.1.3 to 12.1.3 [Release 12.1] Information ...

  6. Android-MediaRecorder录像机(视频)

    在上一篇博客,Android-MediaRecorder录制音频,中讲解了使用Android API MediaRecorder 刻录音频,这篇博客主要是介绍 使用MediaRecorder刻录(视频 ...

  7. DateUtils常用方法

    一.DateUtils常用方法   1.1.常用的日期判断 isSameDay(final Date date1, final Date date2):判断两个时间是否是同一天: isSameInst ...

  8. day14(带参装饰器,迭代器,生成器,枚举对象)

    一,复习 ''' 函数的嵌套定义:在函数内部定义另一个函数 闭包:被嵌套的函数 -- 1.外层通过形参给内层函数传参 -- 2.验证执行 开放封闭原则: 功能可以拓展,但源代码与调用方式都不可以改变 ...

  9. 在DOS命令行窗口中显示系统环境环境变量

    (这是一个小技巧) 示例命令: echo %path% path是系统环境变量,使用百分号包围起来 http://www.cnblogs.com/danzhang 张洪君 微软ALM MVP

  10. Hadoopd 单元测试-MPUnit

    Apache 版: 官网:http://mrunit.apache.org 教程:https://cwiki.apache.org/confluence/display/MRUNIT/MRUnit+T ...