WCF系列教程之客户端异步调用服务
本文参考自http://www.cnblogs.com/wangweimutou/p/4409227.html,纯属读书笔记,加深记忆
一、简介
在前面的随笔中,详细的介绍了WCF客户端服务的调用方法,但是那些操作全都是同步的,所以我们需要很长的时间等待服务器的反馈,如何一台服务器的速度很慢,所以客户端得到结果就需要很长的时间,试想一下,如果客户端是个web项目,那么客户体验可想而知,所以为了不影响后续代码执行和用户的体验,就需要使用异步的方式来调用服务。注意这里的异步是完全针对客户端而言的,与WCF服务契约的方法是否异步无关,也就是在不改变操作契约的情况下,我们可以用同步或者异步的方式调用WCF服务。
二、操作示例

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks; namespace IService
{
[ServiceContract]
public interface ICalculate
{
[OperationContract]
int Add(int a, int b);
}
}

IUserInfo.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Threading.Tasks; namespace IService
{
[ServiceContract]
public interface IUserInfo
{
[OperationContract]
User[] GetInfo(int? id);
} [DataContract]
public class User
{
[DataMember]
public int ID { get; set; }
[DataMember]
public string Name { get; set; }
[DataMember]
public int Age { get; set; }
[DataMember]
public string Nationality { get; set; }
}
}

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

using IService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Service
{
public class Calculate : ICalculate
{
public int Add(int a, int b)
{
return a + b;
}
}
}

UserInfo.cs

using IService;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Service
{
public class UserInfo : IUserInfo
{
public User[] GetInfo(int? id)
{
List<User> Users = new List<User>();
Users.Add(new User { ID = 1, Name = "张三", Age = 11, Nationality = "China" });
Users.Add(new User { ID = 2, Name = "李四", Age = 12, Nationality = "English" });
Users.Add(new User { ID = 3, Name = "王五", Age = 13, Nationality = "American" }); if (id != null)
{
return Users.Where(x => x.ID == id).ToArray();
}
else
{
return Users.ToArray();
}
}
}
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Service;
using System.ServiceModel; namespace Host
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(Calculate)))
{
host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
host.Open();
Console.Read();
}
}
}
}

App.Config

<?xml version="1.0"?>
<configuration>
<system.serviceModel> <services>
<service name="Service.Calculate" behaviorConfiguration="mexBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:1234/Calculate/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="IService.ICalculate" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services> <behaviors>
<serviceBehaviors>
<behavior name="mexBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

ok,打开Host.exe

服务开启成功!
2、新建名为Client的客户端控制台程序,通过添加引用的方式,异步调用WCF服务
添加添加对服务终结点地址http://localhost:6666/UserInfo/的引用,设置服务命名空间为UserInfoServiceNS,点击高级设置,勾选生成异步操作选项,生成客户端代理类和配置文件代码后,完成Client对服务的调用.


ok,开始编写program.cs代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Client.UserInfoServiceNS; namespace Client
{
class Program
{
static void Main(string[] args)
{
UserInfoClient proxy = new UserInfoClient();
proxy.GetInfoCompleted += new EventHandler<GetInfoCompletedEventArgs>(proxy_GetInfoCompleted);//注册proxy_GetInfoCompleted到proxy.GetInfoCompleted中
proxy.GetInfoAsync(null);//开始异步调用
Console.WriteLine("此字符串在调用方法前输出,说明异步调用成功!");
Console.Read();
} static void proxy_GetInfoCompleted(object sender, GetInfoCompletedEventArgs e)
{
User[] Users = e.Result.ToArray();
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}", "ID", "Name", "Age", "Nationality");
for (int i = ; i < Users.Length; i++)
{
Console.WriteLine("{0,-10}{1,-10}{2,-10}{3,-10}",
Users[i].ID.ToString(),
Users[i].Name.ToString(),
Users[i].Age.ToString(),
Users[i].Nationality.ToString());
}
}
}
}

从上面的代码可以看出WCF服务端和WCF客户端采用了事件驱动机制,也就是所谓的发布-订阅模式,不了解的话,请参考本人的C# 委托,当proxy.GetInfoAsync(null)从服务端获取数据成功之后,即开始执行EventHandler<T>上绑定的方法.
public delegate void EventHandler<TEventArgs>(object sender, TEventArgs e);
通过参数类型TEventArgs的Result可以获得返回结果
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系列教程之客户端异步调用服务的更多相关文章
- WCF初探-11:WCF客户端异步调用服务
前言: 在上一篇WCF初探-10:WCF客户端调用服务 中,我详细介绍了WCF客户端调用服务的方法,但是,这些操作都是同步进行的.有时我们需要长时间处理应用程序并得到返回结果,但又不想影响程序后面代码 ...
- WCF入门教程(三)定义服务协定--属性标签
WCF入门教程(三)定义服务协定--属性标签 属性标签,成为定义协议的主要方式.先将最简单的标签进行简单介绍,以了解他们的功能以及使用规则. 服务协定标识,标识哪些接口是服务协定,哪些操作时服务协定的 ...
- 前端测试框架Jest系列教程 -- Asynchronous(测试异步代码)
写在前面: 在JavaScript代码中,异步运行是很常见的.当你有异步运行的代码时,Jest需要知道它测试的代码何时完成,然后才能继续进行另一个测试.Jest提供了几种方法来处理这个问题. 测试异步 ...
- spring cloud系列教程第八篇-修改服务名称及获取注册中心注册者的信息
spring cloud系列教程第八篇-修改服务名称及获取注册中心注册者的信息 本文主要内容: 1:管理页面主机名及访问ip信息提示修改 2:获取当前注册中心的服务列表及每个服务对于的服务提供者列表 ...
- 【转】无废话WCF系列教程
转自:http://www.cnblogs.com/iamlilinfeng/category/415833.html 看后感:这系列的作者李林峰写得真的不错,通过它的例子,让我对WCF有了一 ...
- WCF系列教程之初识WCF
本随笔参考自WCF编程系列(一)初识WCF,纯属读书笔记,加深记忆. 1.简介:Windows Communication Foundation(WCF)是微软为构建面向服务的应用程序所提供的统一编程 ...
- Webservice客户端动态调用服务端功能方法
一.发布WebService服务 方式一:在服务端生成wsdl文件,下方客户端直接引用即可 优点:针对要发布的方法生成一个wsdl文件即可,无需多余配置. 缺点:每次服务端方法发生改变都需 ...
- cxf 生成客户端代码调用服务
cxf是另一种发布webservice的方式,与jdk提供的相比 jdk提供的是wsimport cxf 提供的是 wsdl2java- d 地址 根据http://www.cnblogs.com/f ...
- 通过.NET客户端异步调用Web API(C#)
在学习Web API的基础课程 Calling a Web API From a .NET Client (C#) 中,作者介绍了如何客户端调用WEB API,并给了示例代码. 但是,那些代码并不是非 ...
随机推荐
- Word2007发布博客
目前大部分的博客作者在用Word写博客这件事情上都会遇到以下3个痛点: 1.所有博客平台关闭了文档发布接口,用户无法使用Word,Windows Live Writer等工具来发布博客.使用Word写 ...
- linux每天一小步---rm命令详解
1 命令功能 rm命令用于删除文件或者目录,值得注意的是linux下的删除不弯曲等同于windows系统下的删除操作,linux系统下一旦删除了文件或者目录那么它将消失,而windows系统下我们还可 ...
- Android-操作系统拨打电话广播的处理
Android操作系统的 packages/apps/phone/AndroidManifest.xml源码阅读 在之前的博客,Android-隐式意图激活操作系统通话界面,讲解了,阅读Android ...
- Spring AOP 自定义注解获取http接口及WebService接口入参和出参
注解方法实现过程中可以采用如下获取方式:—以下为例 HttpServletRequest request = ((ServletRequestAttributes) RequestContextHo ...
- subprocess.Popen命令如何隐藏弹框
在用PYQT编写GUI界面时,代码中有用到subprocess.Popen(),打包exe后每次遇到subprocess语句是就会弹出命令框,很是头疼, 下面是解决的办法 import subproc ...
- spark任务提交到yarn上命令总结
spark任务提交到yarn上命令总结 1. 使用spark-submit提交任务 集群模式执行 SparkPi 任务,指定资源使用,指定eventLog目录 spark-submit --class ...
- [.net]ConcurrentBag源码分析
ConcurrentBag根据操作线程,对不同线程分配不同的队列进行数据操作.这样,每个队列只有一个线程在操作,不会发生并发问题.其内部实现运用了net4.0新加入的ThreadLocal线程本地存储 ...
- Code Chef IMPO(计算几何+扫描线+积分)
题面 传送门 前置芝士 扫描线,积分求面积 题解 我怎么老是忘了积分可以求面积-- 首先,这两个投影的最小的\(x\)坐标和最大的\(x\)坐标必须相等,否则肯定无解 我们考虑一种方法,枚举\(x\) ...
- [Objective-C语言教程]类别(28)
有时,可能会发现希望通过添加仅在某些情况下有用的行为来扩展现有类. 要向现有类添加此类扩展,Objective-C提供了类别和扩展. 如果需要向现有类添加方法,或许为了添加功能以便在应用程序中更容易地 ...
- [CISCO] 思科交换机基本配置
思科交换机基本配置 交换机是局域网中最重要的设备,交换机是基于 MAC 来进行工作的.和路由器类似,交换 机也有 IOS,IOS 的基本使用方法是一样的.本章将简单介绍交换机的一些基本配置,以及交换 ...