zoukankan      html  css  js  c++  java
  • WCF中的异步实现技术剖析

    对于WCF中通讯的双方来说,客户端可以异步的调用服务;服务端对服务也能以异步的方式实现。这就涉及到两个方面:WCF客户端异步调用服务;服务端的异步实现本节是Artech《WCF技术剖析(卷1)》一篇读书笔记。在文章中老A介绍了客户端如何以异步的方式消费WCF服务,以及服务的异步实现,个人对这几种方式做个总结。
     

     

    目录:
    1. WCF客户端异步调用服务
    2. 服务端的异步实现 

     

     
    WCF客户端异步调用服务主要通过生成异步的代理类,然后调用其中的异步方法来实现异步调用。
    异步代理类的生成:

     

    • 通过SvcUtil  /async   直接生产异步代理;
    • 通过添加应用的方式,点击”添加引用“的“高级”按钮,在弹出来的对话框中选择“生成异步”。如图:

     

    生成的异步调用代理类部分借口:

     

     

           
    复制代码
           [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]

    public System.IAsyncResult BeginAdd(int x, int y, System.AsyncCallback callback, object asyncState) {
                return base.Channel.BeginAdd(x, y, callback, asyncState);
            }


            public void AddAsync(int x, int y) {
                this.AddAsync(x, y, null);
            }

            public void AddAsync(int x, int y, object userState) {
                if ((this.onBeginAddDelegate == null)) {
                    this.onBeginAddDelegate = new BeginOperationDelegate(this.OnBeginAdd);
                }
                if ((this.onEndAddDelegate == null)) {
                    this.onEndAddDelegate = new EndOperationDelegate(this.OnEndAdd);
                }
                if ((this.onAddCompletedDelegate == null)) {
                    this.onAddCompletedDelegate = new System.Threading.SendOrPostCallback(this.OnAddCompleted);
                }
                base.InvokeAsync(this.onBeginAddDelegate, new object[] {
                            x,
                            y}, this.onEndAddDelegate, this.onAddCompletedDelegate, userState);
            }

    复制代码
     

    1、客户端异步调用服务

    客户端异步调用服务主要方式有几种:

    1.1、直接调用异步方法:
    在生成的代理类中,有BeginAdd\EndAdd等服务契约中定义的Add操作的异步实现。直接调用BeginAdd方法,实现客户端异步调用服务端方法。在调用BeginAdd方法后,可执行一些其他操作,这些操作与服务端Add调用并行执行,Add调用最终通过EndAdd方法得到。
     

    测试代码如下:

    客户端代码:
    复制代码
    IAsyncResult asyncResult = calculatorClient.BeginAdd(1for (int i = 0; i < 10; i++) 

    {
        Console.WriteLine(i);
    }
    int resul = calculatorClient.EndAdd(asyncResult);
    Console.WriteLine(string.Format("计算结果:{0}",resul));

    复制代码
     
    服务端代码:
       
    复制代码
        public int Add(int x, int y) 

        {
            for (int i = 0; i < 20; i++)
           {
            Console.WriteLine(i);
           }
           Console.WriteLine("开始计算...");
           return x + y;
        }

    复制代码
     

    服务端输出如下:

     

     客户端输出如下:

     

    这种方式使用了EndAdd方法,如果服务端没有执行完成,当前线程会被阻塞直到异步调用的服务完成后结束。如客户端代码保持不变,将服务实现改为如下:
     
    复制代码
    for (int i = 0; i < 20; i++)  

    {
        Console.WriteLine(i);
    }
    Thread.Sleep(5000);
    Console.WriteLine("开始计算...");
    return x + y;

    复制代码
     
    如果在服务端让线程睡眠几秒,就可看到客户端会被阻塞:

     

    1.2、通过回调的方式异步调用服务:
    在生成的异步调用代理类中,还可以通过回调用服务;
    复制代码
    IAsyncResult asyncResult = calculatorClient.BeginAdd(12

    delegate(IAsyncResult asyncResult)
                                              {
                                                    int [] array = asyncResult.AsyncState as int [];
                                                    int result= calculatorClient.EndAdd(asyncResult1);
                                                    calculatorClient.close()
                                                    Console.WriteLine(string.Format("{0}+{1}={2}", array[0], array[1], result));
                                               }, new []{1,2});

    复制代码
     

    这种方式是对服务的异步调用完成以后,自动调用回调来获取结果。

     
    1.3、通过为异步操作注册事件
    复制代码
    //进行异步调用 

    calculatorClient.AddAsync(1036new[] { 1000 });

    //为异步调用完成定义触发事件 

    calculatorClient.AddCompleted += calculatorClient_AddCompleted;
    Console.WriteLine("服务调用完成...");
    Console.ReadKey();
      

    //异步调用完成后执行 

    privatestaticvoid calculatorClient_AddCompleted(object obj, AddCompletedEventArgs args)
    {
        var array = args.UserState as int[];
        int result = args.Result;
        Console.WriteLine(result);
    }

    复制代码
     
    2、服务的异步实现:
    将服务实现定义成异步的方式,需要将OperationContract的AsyncPattern设置为true;应用到BeginXX接口上,并且此操作的最后两个参数必须为AsyncCallback ,object;需要有一个EndXX(IAsyncResult asyncResult)的接口与异步调用的接口匹配。需要注意的是EndXX(IAsyncResult asyncResult)不能再次声明为契约接口,也就是不能再标记为OperationContract。

    将服务定义为异步服务,契约定义如下 :

     
    复制代码
    [OperationContract(AsyncPattern = true)]  

    IAsyncResult BeginCalculator 
    (int x,int y ,AsyncCallback asyncCallback, object state);

     

    void EndCalculator(IAsyncResult);

    复制代码
     

    然后在实现契约接口的服务中,将方法实现为异步的。

     
    将契约接口声明为单向,也就是OneWay,这样客户端对此服务接口调用就是异步的。因为它无需等待服务端返回,客户端只需将消息发送到传输层就立即返回。
    那能不能将将这种客户端对服务端的异步调用直接标记为单向的,那是不是可以不用生成异步代理类(即上述SvcUtil /Ayncs或者在添加引用时声明将代理类生成异步操作)?答案是否定的,因为OneWay要求方法的返回值为void,而异步的方法需要IAsyncResult最为返回值,这两者矛盾的。
     
     
     
    分类: WCF基础
  • 相关阅读:
    Android自定义之仿360Root大师水纹效果
    Android之TextView的Span样式源码剖析
    Android之TextView的样式类Span的使用详解
    随着ScrollView的滑动,渐渐的执行动画View
    仿微信主界面导航栏图标字体颜色的变化
    android自定义之 5.0 风格progressBar
    Android性能优化之内存篇
    Android性能优化之运算篇
    How to install Zabbix5.0 LTS version with Yum on the CentOS 7.8 system?
    How to install Zabbix4.0 LTS version with Yum on the Oracle Linux 7.3 system?
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2459857.html
Copyright © 2011-2022 走看看