zoukankan      html  css  js  c++  java
  • 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 = 0; 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);

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

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

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

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

    (1)、打开cmd,输入cd C:Program Files (x86)Microsoft SDKsWindowsv7.0ABin

    (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)、剩下的步骤和上面的一样

  • 相关阅读:
    C#的dll被其他程序调用时,获取此dll正确的物理路径
    用鼠标右键选择DataGridView单元格或行
    当心回车符破坏你的JSON数据
    WinForm中当TextBox重新获得焦点时输入法失效问题
    django-rest-framework登陆认证
    django-celery定时任务以及异步任务and服务器部署并且运行全部过程
    linux安装mysqlclient报错
    Dajngo的CBV和FBV
    五分钟看懂Celery定时任务
    Nginx+uWsgi生产部署Django
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/6861590.html
Copyright © 2011-2022 走看看