WCF开发实战教程

来源:互联网 发布:大兄何见事之晚乎的之 编辑:程序博客网 时间:2024/06/07 01:16

WCF开发实战系列教程

 

1:创建第一个WCF服务

在这个实战中我们将使用DataContract,ServiceContract来构建WCF服务,并使用VS2008内置的“WCFSVCHost”运行我们创建的WCF服务,并使用“WCF测试客户端来测试我们创建的服务。
在此WCF服务中我们将建立一个关于Book的服务,并实现对Book的添加、删除和检索操作。

第一步:创建“WCF服务库
文件(F)”->“新建项目(P)...”打开新建项目对话框。在左侧的项目类型中选择“WCF”,然后再在右侧的模板中选择“WCF服务库
在下面的名称文本框中,填写我们要创建的WCF服务库的项目名称“Services”

《图1
点击确定,会创建出我们的WCF服务库项目,在解决方案中会自动为我们生成两个类文件“IService.cs”“Service.cs”

《图2
这两个类文件是两个WCF示例文件,对我们开发没有什么用处,现在我们删掉这两个文件。

第二步:创建Book实体类
解决方案窗口中,我们右击Services项目名,选择添加,再单击


《图3
在弹出的添加新项窗口中,选择,并在名称文本框中写入项名称“Book.cs”


《图4

第三步:为Book实体类编写代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
usingSystem.Runtime.Serialization;

namespace Services
{
    
[DataContract]
    public class Book
    {
        [DataMember]
        public string BookNO;
        [DataMember]
        public string BookName;
       [DataMember]
        public decimal BookPrice;
    }
}
为了保证此类在WCF调用中能够被序列化,我们在Book类上面加入[DataContract]标签,在每个需要序列化的成员变量上加入[DataMember]标签。这两个标签在使用的进候需要导入using System.Runtime.Serialization命名空间。
到此为至,我们创建完了需要在服务中传输的复杂的数据类型Book

第四步:创建服务接口
创建服务接口,声明对外发布的类和方法。
解决方案窗口中,我们右击Services项目名,选择添加,再单击



《图3
在弹出的添加新项窗口中,选择,并在名称文本框中写入项名称“IBookService.cs”


《图5
在此类文件中我们编写服务接口,代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
usingSystem.ServiceModel;

namespace Services
{
   
[ServiceContract]
    public interface IBookService
    {
        [OperationContract]
        void AddBooks(Bookbook);
       [OperationContract]
        List<Book>GetAllBooks();
        [OperationContract]
        void RemoveBook(stringid);
    }
}
IBookService接口上面,我们定义了[ServiceContract]标签,此标签代表此接口及实现此接口的类都是对外发布的Service类,在每个需要对外发布的方法上都加上[OperationContract]标签,以使外部可以访问到此方法。
[ServiceContract]
[OperationContract]这两个标签需要导入using System.ServiceModel命名空间。

第五步:创建实现服务接口的类
实现我们上面声明的服务接口,实现对Book的添加、删除和检索的具体功能。
解决方案窗口中,我们右击Services项目名,选择添加,再单击



《图3
在弹出的添加新项窗口中,选择,并在名称文本框中写入项名称“BookService.cs”


《图6
在此类文件中编写代码实现IBookService.cs服务接口。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
usingSystem.ServiceModel;

namespace Services
{
    
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class BookService : IBookService
    {
        List<Book> _Books = newList<Book>();
        public void AddBooks(Bookbook)
        {
            book.BookNO= Guid.NewGuid().ToString();
           _Books.Add(book);
        }

        publicList<Book> GetAllBooks()
        {
            return_Books;
        }

        public void RemoveBook(stringid)
        {
            Book book =_Books.Find(p => p.BookNO == id);
           _Books.Remove(book);
        }
    }
}
此类是对IBookService接口的具体实现,在此类的上面我们声明了[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]标签,此标签代表这个类采用SingleTone(单类模式)来生成对象。
使用[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]接口需要导入using System.ServiceModel;命名空间。

第六步:配置WCF服务
到目前为至,我们建立好了WCF服务,那我们如何让WCFSVCHost(WCF服务主机)理解我们编写的服务类,并能够运行我们编写的服务呢。这需要我们在App.Config里面注册一下我们的WCF服务。
代码如下:
<system.serviceModel>
    <services>
      <servicebehaviorConfiguration="Services.Service1Behavior"name="Services.BookService">
        <endpoint address=""binding="wsHttpBinding"contract="Services.IBookService">
          <identity>
            <dnsvalue="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex"binding="mexHttpBinding" contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <addbaseAddress="
http://localhost:8731/Design_Time_Addresses/Services/Service1/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behaviorname="Services.Service1Behavior">
          <!--
为避免泄漏元数据信息,
         
请在部署前将以下值设置为 false并删除上面的元数据终结点 -->
          <serviceMetadatahttpGetEnabled="True"/>
          <!--
要接收故障异常详细信息以进行调试, 
         
请将下值设置为 true。在部署前 
           
设置为 false以避免泄漏异常信息-->
          <serviceDebugincludeExceptionDetailInFaults="False" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
</system.serviceModel>

这么多东西谁能记得下?!!!
没关系,VS2008为我们提供了可视化的操作界面。
Services项目中右击“App.Config”配置文件,在弹出的右键菜单中选择编辑WCF配置


《图7
弹出界面如下:


《图8
在此界面中暴露两个对外的终结点(外部可以访问到的类或接口),其中下面一个是元数据终结点,用来向外提供服务信息的终结点。而另一个(即上面的终结点),是向外公布我们编写的[ServiceContract]的类,但我们可以看到它的Contract还是我们在第一步中删掉的Services.IService1这个终结点。不仅如此,在右侧的服务中还依旧是我们在第一步中删除的Services.Service1服务。这说明虽然在第一步中我们删除了那两个自动生成的类文件,但配置文件中仍没有删除这两个类文件的配置信息。
下面我们把它们改变一下。
单击左侧的服务”-“Services.Service1”在右侧的Name,弹出服务类型浏览器对话框,在此类型中我们找到此WCF服务项目编译出来的Services.dll文件,双击它就可以出现此服务中的对外公布的服务,点击选中它单击确定。


《图9
这样我们就可以把对外公司的服务改变为我们刚编写的服务了。
然后,我们展开左侧服务”->“Services.BookService”->“终结点,单击第一个空名称,从右边的终结点属性中的Contract中我们可以看到,这里的Contract仍然用的是Services.IService1


《图10
那我们按照上面的做法,找到此WCF服务项目编译出来的Services.dll,双击它找到里面对应的ServiceContract点击确定就可以了。


《图11
点击菜单文件”-“保存就可以把我们对App.Config的修改保存回配置文件了。

OK,现在我们对WCF的配置算是完成了

第七步:运行WCF进行测试。
   
VS2008中为我们提供了测试WCF的工具,按F5启动WCF会出现两个东西
   
一个是在右下角的托盘图标中会出现WCFSVCHost(WCF服务主机),它为我们在开发时候提供了一个运行WCF的服务器,用来为测试客户端提供WCF服务。


   
图《12
   
另一个是“WCF测试客户端


   
图《13
    “
测试客户端WcfSVCHost中取得WCF服务的元数据,解析为右侧的服务结构树,从这里面我们可以看到此WCF服务为我们提供了一个服务契约“IBookService”,此服务契约中对外提供了三个可调用的方法。
   
双击AddBooks()方法,我们可以从右面输入相关的数据然后点击调用,就可以把数据送给WCF服务器,去调用对应的方法了。


   
图《14
   
双击GetAllBooks方法,我们可以查看添加的书的信息


   
图《15
   
双击RemoveBoo()方法就可以把书删除


   
图《16


 

2: 使用IIS发布WCF服务  

    上一篇中,我们创建了一个简单的WCF服务,在测试的时候,我们使用VS2008自带的WCFSVCHost(WCF服务主机)发布WCF服务,以便进行测试。这种VS2008内置的WCFSVCHost只适用于开发人员测试的使用,能进行WCF服务部署。这一篇文章中我们来看一下如何在IIS中部发布我们上一篇中做好的WCF服务。

第一步:打开我们上一篇文章中建立的WCF服务项目。


图《1

第二步:新建WCF服务站点。在解决方案上右击,选择添加”->“新建网站,打开新建网站对话框。在添加新网站对话框中,我们选择“WCF服务,并把网站的名子命名为“BookServiceHost”


图《2
建立起来的新的WCF服务站点的结果如下,其中在App_Code文件中自动为我们生成两个类文件:IService.csService.cs。这两个文件对我们来说没有用,我们删掉。


图《3

第三步:在刚刚创建的WCF服务站点上添加对WCF服务库项目--Services项目的引用。


图《4

第四步:配置Service.svc文件。
双击Service.svc文件,我们可以看到它的声明指示如下:
<%@ ServiceHost Language="C#" Debug="true"Service="Service" CodeBehind="~/App_Code/Service.cs" %>
由于在第二步中我们已经把IService.csService.cs两个文件已经删除了,所以这里的声明指示内容修改一下,让这个Service.svc文件的后台代码指向我们上次创建的WCF服务库项目--Services项目中的类,改后的代码如下:
<%@ ServiceHost Language="C#" Debug="true"Service="Services.BookService"%>
我们把其中的Service属性指定为Services命名空间下的BookService类,并把CodeBehind属性删去了。

第五步:配置此WCF服务站点与WCF服务库项目之间的类的对应。
虽然在第三步中我们添加了对Services项目的引用,并且在第四步中修改了Service.svc的类的对应,但此时我们的WCF服务站点并不能把WCF服务库中的服务和终结点发布出来,还需要我们对web.config进行一系列的配置工作。
web.config上右击选择编辑WCF配置


《图5
在弹出的服务配置窗口中,把Service服务指定到WCF服务库的Services.dll中的Services.BookService服务类上。


《图6
再把其中的一个对外终结点的Contract设为WCF服务库的Services.dll中的Services.IBookService服务契约上。


《图7

第六步:试着再添加一个通信的终结点。
这一步是可选的,我们再为此WCF服务站点添加一个终结点,A=basicB=basicHttpBinding C=Services.IBookService


《图8
下面我们将试着使用不同的终结点与WCF服务进行交互,查看运行情况。
当我们使用IIS5IIS6发布WCF服务的时候一般只创建Http绑定的终结点,而不能创建使用TCP绑定、管道绑定的终结点。

第七步:测试运行WCF服务站点。
Service.svc上右击,选择在浏览器中查看,在IE中运行此服务。


《图9
由此我们看到我们可以在ASP.NET Development Server中发布我们的WCF服务了。

第八步:在IIS布署此WCF服务站点。
IIS建立Web应用程,指向我们的WCF服务站点所在的目录。然后在IIS运行我们发布的WCF服务


《图10
从上图中我们看到发布的站点中不再包含有端口号。
到此为至我们在IIS中发布WCF服务成功。

下面我们在WCF测试客户端调用我们刚刚在IIS中发布的WCF服务
第九点:在VS2008命令窗口中输入以下代码运行WCF测试客户端
   x:\...\wcftestclient 
http://localhost/TestWCFService/Service.svc
弹出测试窗口如下:


《图11
我们可以看到发布的服务中有两个终结点:这两个终结点的传输方式不同,但提供的方法是相同的。
我们通过第一个终结点的AddBooks()方法添加三个对象。


《图12
再通过第二个终结点的GetAllBooks()方法取得所有对象的信息。


《图13
运行完全没问题。

 

3:自运行WCF服务


 

上一篇文章中我们建立了一个WCF服务站点,为WCF服务库运行提供WEB支持,我们把这个WCF服务站点布署到IIS中去,实现WCF服务在Web上的发布。
这一篇文章中我们来谈一下自运行WCF服务。什么是自运行WCF服务呢?就是通过我们编写的控制台程序或WinForm程序来为本机或远程机提供WCF服务的方式。

下面我们使用控制台程序来提供WCF的自运行服务

第一步:建立控制台应用程序ConsoleBookServiceHost


《图1
第二步:向ConsoleBookServiceHost程序中添加两个引用:一个是WCF服务库Services项目的引用,另一个是System.ServiceModel引用。
第三步:在ConsoleBookServiceHost项目中的Program.cs中编写代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Services; //
导入WCF服务库项目命名空间
usingSystem.ServiceModel;//
导入WCF服务命名空间

namespace ConsoleBookServiceHost
{
    public class Program
    {
        public static void Main(string[]args)
        {
            //
实例化ServiceHost服务承载器,并在构造函数中指定要发布的BookService
            
ServiceHost host = new ServiceHost(typeof(BookService));
            //打开服务承载器,读取配置文件中的WCF服务的配置信息
           
host.Open();
           Console.WriteLine("服务已启动......");
           Console.ReadLine();
            
host.Close();
        }
    }
}

第四步:在ConsoleBookServiceHost中添加配置文件App.Config


《图2

第五步:在App.Config上右击选择选择编辑WCF配置,弹出服务配置管理窗口


《图3
由于该App.Config文件是我们新添加的一个配置文件,所以左边的服务项中是空的。

第六步:点击右边的新建服务...”弹出新建服务元素向导窗口,单击浏览按钮,选择Bin/Debug目录下Services.dll程序集中的Services.BookService服务。


《图4

第七步:单击下一步,是选择服务契约项,单击浏览按钮,选择Bin/Debug目录下Services.dll程序集中的Services.IBookService服务契约。


《图5

第八步:单击下一步,是选择通信模式的界面。在这里我们先选择Http


《图6

第九步:单击下一步,是选择Http通信的互操作方式。界面中有两项供我们选择:基本Web互操作性和高级web互操作性。在这里我们选择第一项


《图7

第十步:单击下一步,是选择终结点地址,也就告诉程序访问这个终结点的路径地址。这里的地址可以使用http://....格式的绝对地址,也可以像图中那样使用相对地址。


《图8
第十一步:单击下一步,出来配置成功界面,单击完成完成此次配置


《图9
此时WCF配置窗口中会出现一个服务节点,其中的终结点就是我们刚才配置信息A=basic B=basicHttpBinding C=Service.IBookService


《图10

第十二步:下面我们再使用向导添加一个终结点
点击左侧的服务节点,出现界面如下:


《图11
点击新建服务终结点...”处弹出向导,选择服务契约



《图5
点击下一步出现界面选择通信模式,这里我们还是选择Http



《图6
点击下一步出现界面互操作方式,这里我们选择高级web互操作性,这种互操作方式的安全性比较高


《图12
点击下一步出现界面选择终结点地址,这里我们使用相对地址,填写 ws


《图13
点击下一步出现配置成功界面,单击完成完成此次配置


《图14
此时WCF配置窗口中又会多出一个服务节点,其中的终结点就是我们刚才配置信息A=ws B=ws2007HttpBinding C=Service.IBookService


《图15

到目前为止我们配置好了两个http通道下的两个终结点,但这两个终结点的地址我们都使用的是相对地址,它们是相对于当前ServiceHost地址,所以我们还需要配置当前ServiceHost的地址.

第十三步:配置ServiceHost的地址:
点击左侧配置中的主机,在右边点击新建按钮,在弹出的窗口中写入ServiceHost的地址,在这里可以选择使用端口号。


《图16
这样我们两个终结点算是配置完成了。

自运行WCF服务与上一篇说的IIS布运行WCF服务不一样的是,自运行WCF服务"除了可以使用Http方式发布WCF服务,可以使用TCP、命名管道和微软消息队列进行信息传输。
下面我们再配置两个终结点,一个是使用TCP通信模式,另一个使用命名管道通信模式。

第十四步:添加一个新的TCP终结点,配置如下:


《图17

第十五步:添加一个新的命名管道终结点,配置如下:


《图18

到此为至,我们已经为该WCF服务建立了四个数据传输的终结点:


《图19

下面我们为该ServiceHost程序配置元数据终结点,以向客户端发送服务元数据信息

第十六步:添加服务行为。在左侧配置中选择高级”-“服务行为,再点击右侧的新建服务行为分配


《图20


《图21

在上图中,点击添加弹出添加行为元素扩展部份窗口,选择“serviceMetaData”


《图22

第十七步:为服务配置刚刚新建的行为。


《图23

第十八步:配置元数据终结点:


《图24


《图25


《图26


《图27


《图28


《图29

此时我们运行的时候,会出现错误如下(无法加载配置中的x.509证书标识):


《图30
我们看一下App.config配置文件中的代码如下:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.serviceModel>
        <behaviors>
           <serviceBehaviors>
               <behavior name="NewBehavior">
                   <serviceMetadata />
               </behavior>
            </serviceBehaviors>
        </behaviors>
        <services>
            <servicebehaviorConfiguration="NewBehavior"name="Services.BookService">
               <clear />
               <endpoint address="basic" binding="basicHttpBinding"contract="Services.IBookService"
                   listenUriMode="Explicit">
                   <identity>
                       <certificateReference storeName="My"storeLocation="LocalMachine"
                           x509FindType="FindBySubjectDistinguishedName" />
                   </identity>
               </endpoint>
               <endpoint address="ws" binding="ws2007HttpBinding"contract="Services.IBookService"
                   listenUriMode="Explicit">
                   <identity>
                       <certificateReference storeName="My"storeLocation="LocalMachine"
                           x509FindType="FindBySubjectDistinguishedName" />
                   </identity>
               </endpoint>
               <endpoint address="net.tcp://localhost:8082/BookService"binding="netTcpBinding"
                   contract="Services.IBookService"listenUriMode="Explicit">
                   <identity>
                       <certificateReference storeName="My"storeLocation="LocalMachine"
                           x509FindType="FindBySubjectDistinguishedName" />
                   </identity>
               </endpoint>
               <endpoint address="net.pipe://localhost/BookService"binding="netNamedPipeBinding"
                   contract="Services.IBookService"listenUriMode="Explicit">
                   <identity>
                       <certificateReference storeName="My"storeLocation="LocalMachine"
                           x509FindType="FindBySubjectDistinguishedName" />
                   </identity>
               </endpoint>
               <endpoint address="mex" binding="basicHttpBinding"bindingConfiguration=""
                   contract="IMetadataExchange" />
               <host>
                   <baseAddresses>
                       <add baseAddress="
http://localhost:8081/BookService" />
                   </baseAddresses>
               </host>
           </service>
        </services>
    </system.serviceModel>
</configuration>

把其中的
<identity>
   <certificateReference storeName="My"storeLocation="LocalMachine"
       x509FindType="FindBySubjectDistinguishedName" />
</identity>

都删掉。

Ctrl+F5运行即可。

至此,我们把用来提供 WCF服务的运行程序编写完成了。


测试一下。
选按Ctrl+F5运行我们上面编写的ServerHost程序
打开浏览器,在地址栏中输入第十三步中ServerHost中的地址,出现如下界面:


《图31
从图中我们可以看出,这个Service页面就是通过我们上面的ServiceHost程序来提供的WCF服务


下面我们再通过wcftestclient来测试一下
选按Ctrl+F5运行我们上面编写的ServerHost程序
再打开VS2008DOS窗口,输入wcftestclient http://localhost:8081/BookService出现界面如下:


《图32
从图中我们可以看出,我们为BookService配置的四个终点都显示出来了,我们可以使用不同的终结点添加书目信息,然后再用其它的终结点取出书目信息。因为这四个不同通道的终结点都是操作同一个服务。

4:使用Windows服务发布WCF服务

上一篇文章中我们通过编写的控制台程序或WinForm程序来为本机或远程机提供WCF服务的方式,我们称这种方式为Self-Host服务发布方式,这一篇文章我们来看一下如何编写Windows服务来发布WCF服务。

第一步:建立Windows服务程序WindowsServiceHost


《图1


《图2

第二步:向ConsoleBookServiceHost程序中添加两个引用:一个是WCF服务库Services项目的引用,另一个是System.ServiceModel引用。

第三步:修改Service1的属性
Service1的设计界面中右击,选择属性,把其中的(Name)ServiceName都改为BookServiceHost


《图3

第四步:在Service1中编写代码如下


《图4

第五步:配置App.Config
在这里我们不再详细说明如何配置了,我们直接把上一次SelfHostBookService项目中的App.Config复制过来却可


《图5

到这里我们已经作好一个可以发布BookService服务的Windows Service宿主程序了。
下面我们要看一看如何把这个Windows Service运行起来。

第六步:为服务添加安装程序。
Service1设计界面中右击,选择添加安装程序


《图6
生成安装程序组件,出现界面如下


《图7
serviceProcessInstaller1
:服务安装的信息


《图8
serviceInstaller1
:服务本身的信息


《图9
编译成功

第七步:安装上面编写完的服务
打开VS2008命令窗口,进入当前项目的bin/Debug文件夹中,执行命令installutil WindowsServiceHost.exe


《图10


《图11

第八步:启动BookServiceHost服务
打开服务管理器,我们可以看到我们刚刚注册上的服务已经存在了,但还没有启动,右击启动


《图12

第九步:测试服务:
打开IE,在地址栏中输入:http://localhost:8081/BookService 出现下面的界面


《图13
VS2008命令窗口中输入:wcftestclient http://localhost:8081/BookService 出现下面的界面


《图14
调用相应终结点的方法添加书籍,运行正常。


 

 

5:创建WCF客户端程序

在前面的三篇文章中我们分别介绍了WCF服务的三种载体:IISSelf-HostWindows Service Host。当WCF编写完成后我们一般要通过这三种方式的一种发布WCF服务,当WCF服务发布后,我们就可以编写客户程序来与服务的终结点进行通信。
这篇文章我们主要来介绍如何编写客户程序。

前提:
1.
事先建立好一个WCF服务
2.
使用上面任何一种方式发布WCF
在这里我们使用上篇文章中介绍的WindowsServiceHost发布BookService程序。


《图1


《图2

第一步:新建一个项目
此项目可以是控制台程序、WinFormASP.NET中的任何一个,甚至还可以是其它语言的应用程序,如:JavaEE等。
在这里我使用控制台程序为例,建立一个客户项目Client


《图3

第二步:为此项目添加Web引用。
右击项目名称,选择添加服务引用...”


《图4

在弹出的添加服务引用的对话框中,在地址栏里我们输入前面我们发布的WCF服务的终结点的地址http://localhost:8081/BookService
点击前往后,会到上面的地址中去下载WCF服务的元数据,根据接收到的元数据信息,在服务列表中显示出该地址中相应的服务(BookService),展开BookService会看到该服务的服务契约(IBookService),点击IBookService,我们会看到该服务契约中包含的方法契约。

命名空间文本框中为该服务引用指定命名空间,此处为WS

《图5

点击完成,在解决方案管理器中我们可以看到添加完服务引用后的项目。它会自动为我们添加System.ServiceModelSystem.Runtime.Serialization两个本地引用和一个WS服务引用。


《图6

双击打开App.Config会发现里面的内容都自动配置好了,


《图7

右击服务引用WS,选择在对象浏览器中查看,会在对象浏览器中显示出该服务引用的元数据结构。


《图8


《图9
到目前为至,我们把WCF服务引用添加到了我们Client程序中了。

第三步:编写客户端程序代码访问WCF服务
实例化BookServiceClient,它是我们访问WCF服务的代理类。
BookServiceClient实例化时,需要在此类的构造函数中指定访问WCF服务的终结点的名称。
我们打开App.Config,在想要与客户端进行通讯的<endpoint>元素中找到其“name”属性,并把该属性的值复制并粘贴到BookServiceClient的构造函数中。

WS.BookServiceClient client = newClient.WS.BookServiceClient("NetNamedPipeBinding_IBookService");

使用client对象与WCF服务通信,添加两本书。
WS.Book book1 = newClient.WS.Book();
book1.BookName = "
赢在中国";
book1.BookPrice =28.8M;
client.AddBooks(book1);

WS.Book book2 = new Client.WS.Book();
book2.BookName = "
东周列国传";
book2.BookPrice =52.0M;
client.AddBooks(book2);

使用client对象与WCF服务通信,查询现有的书籍列表。
foreach (WS.Book bookin client.GetAllBooks())
{
   Console.WriteLine(book.BookName+"\t"+book.BookPrice);
}

运行结果:


《图10

如果由于网络比较慢,或WCF服务器压力比较大时,当我们Client向他们发出请求时并不会及时得到响应,会出现一段时间的延迟。如果Client是控制台程序就会出现的效果,如果ClientWinForm窗体的话,会出现按钮点下去弹不起来的假死情况,这是因为我们是同步访问WCF服务。一般我们访问远程服务的时候很少使用这种同步访问,因为访问远程服务有好多不确定性,如果使用同步服务的话客户端会需要不断的等待,这是很糟的情况。
下面我们看一下如何使用异步来访问WCF服务。

第一步:修改服务引用的配置。
Web服务引用WS上右击,选择配置服务引用...”,引出配置服务引用对话框。把生成异步引用复选框打上勾。


《图11


《图12

第二步:查看修改完的服务引用
Web服务引用WS上右击,选择在对象浏览器中查看...”,在对象浏览器中我们可以看到BookServiceClient对象中多了好多的方法和事件。这些方法就是为我们产生的异步调用方法。


《图13


《图14

第三步:修改客户端代码:

static void Main(string[] args)
{
    
WS.BookServiceClient client = newClient.WS.BookServiceClient("NetNamedPipeBinding_IBookService");
    //指定异步添加书籍完成后要执行的方法
    
client.AddBooksCompleted += newEventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_AddBooksCompleted);
    //指定异步查询书籍完成后要执行的方法
    
client.GetAllBooksCompleted += newEventHandler<Client.WS.GetAllBooksCompletedEventArgs>(client_GetAllBooksCompleted);

    WS.Book book1 = new Client.WS.Book();
    book1.BookName = "
赢在中国";
    book1.BookPrice = 28.8M;
    //
调用异步添加书籍
    
client.AddBooksAsync(book1);

    WS.Book book2 = new Client.WS.Book();
    book2.BookName = "
东周列国传";
    book2.BookPrice = 52.0M;
    //
调用异步添加书籍
    
client.AddBooksAsync(book2);

    //调用异步显示书籍
    
client.GetAllBooksAsync();
    Console.ReadLine();
}
//异步显示书籍要执行的方法,打印书籍列表
static void 
client_GetAllBooksCompleted(objectsender, Client.WS.GetAllBooksCompletedEventArgs e)
{
    foreach (WS.Book book in e.Result)
    {
        Debug.WriteLine(book.BookName);
    }
}
//异步添加书籍完成后要执行的方法,显示BookAddOver字样
static void 
client_AddBooksCompleted(objectsender, System.ComponentModel.AsyncCompletedEventArgs e)
{
    Debug.WriteLine("BookAddOver");
}

运行结果:


《图15

 


0 0
原创粉丝点击