zoukankan      html  css  js  c++  java
  • 看看async,await 是如何简化异步的调用WCF!

    A:调用WCF难吗?

    B:不难

    A:异步调用WCF难吗?

    B:不难,

    A:异步的调用WCF,并且需要保证异步的调用顺序难吗?

    B:不难

    A:那什么难?

    B:异步的调用WCF,并且保证几个异步的调用顺序,并且代码的可读性,可维护性好,难。

    为了演示这个过程,首先需要创建WCF服务应用程序。

    废话不多说:

    接口:

    [ServiceContract]

    public interface IService1

    {

        [OperationContract]

        string Method1();

       

        [OperationContract]

        string Method2();

        [OperationContract]

        string Method3();

    }

    实现:

    public class Service1 : IService1

    {

        public string Method1()

        {

            Thread.Sleep(2000);

            return "method1";

        }

        public string Method2()

        {

            Thread.Sleep(50);

            return "method2";

        }

        public string Method3()

        {

            Thread.Sleep(100);

            return "method3";

        }

    }

    浏览:

    image

    OKWCF服务已经创建成功了。

    现在需要创建Silverlight客户端来调用,之所以使用Silverlight,是因为Silverlight在生成的是异步调用WCF服务的代码。

    首先创建Silverlight 应用程序,

    修改MainPage.xaml 代码,在Grid中增加:

    <Button Content="Third" Click="Third_Click" />

    添加对服务的引用:

    image

    后台代码如下:

    private void Third_Click(object sender, RoutedEventArgs e)

    {

        Service1Client service1 = new Service1Client();

        service1.Method1Completed += (obj1, arg1) =>

            {

                MessageBox.Show(arg1.Result);

            };

        service1.Method1Async();

       

        service1.Method2Completed += (obj2, arg2) =>

        {

            MessageBox.Show(arg2.Result);

        };

        service1.Method2Async();

        service1.Method3Completed += (obj3, arg3) =>

        {

            MessageBox.Show(arg3.Result);

        };

        service1.Method3Async();

    }

    如你所想,

    因为Method1 sleep 2000,Method2 sleep 50 ,Method3 sleep 100.

    所以弹出来的分别是method2,method3,method1.

    如果我想让执行顺序变为method1,method2,method3 ,那么该怎么办呢?

    注意:执行顺序变为method1,method2,method3 的意思不是简单的MessageBox 的弹出顺序,它的意思是执行method1 后再执行method2,执行完method2后再执行method3. 后面不在赘述。

    很简单,修改代码成这样就可以了,我相信很多同学都会写:

    private void Third_Click(object sender, RoutedEventArgs e)

    {

        Service1Client service1 = new Service1Client();

        service1.Method1Completed += (obj1, arg1) =>

            {

                MessageBox.Show(arg1.Result);

                service1.Method2Completed += (obj2, arg2) =>

                {

                    MessageBox.Show(arg2.Result);

                    service1.Method3Completed += (obj3, arg3) =>

                    {

                        MessageBox.Show(arg3.Result);

                    };

                    service1.Method3Async();

                };

                service1.Method2Async();

            };

        service1.Method1Async();

    }

    这段代码,主要是在每个callback里面才调用后面的方法。

    这段代码没什么大的问题,唯一的缺点是嵌套太多,维护很复杂,如果中间的代码再多一点的话,维护会非常困难。

    如果你用IService1接口的话,代码可能会是下面的样子:

    private void Third_Click(object sender, RoutedEventArgs e)

    {

        IService1 service1 = new Service1Client();

        service1.BeginMethod1(ar1 =>

            {

                Dispatcher.BeginInvoke(() =>

                {

                    MessageBox.Show(service1.EndMethod1(ar1));

                    service1.BeginMethod2(ar2 =>

                    {

                        Dispatcher.BeginInvoke(() =>

                        {

                            MessageBox.Show(service1.EndMethod2(ar2));

                            service1.BeginMethod3(ar3 =>

                            {

                                Dispatcher.BeginInvoke(() =>

                                {

                                    MessageBox.Show(service1.EndMethod3(ar3));

                                });

                            }, null);

                        });

                    }, null);

                });

            }, null);

    }

    在这里MessageBox.Show 需要使用Dispatcher.BeginInvoke,否则会提示安全性错误。

    Vs里面的截图是这样的:

    image

    这段代码比刚刚的代码更复杂,相信没有谁愿意维护这样的一大段代码的。

    正是因为这种代码非常常见,但是却很复杂,微软推出了async await 关键字。

    如果要使用async await,需要将vs 升级到sp1,并且下载安装AsyncCtp,在这里我假设大家都已经安装了扩展了。

    如何使用,第一步需要在Silverlight 应用程序中添加对AsyncCtpLibrary_Silverlight 的引用。

    clip_image002

    一切准备就绪后,就可以使用async,await 了。

    image

    可以看到使用async ,await 代码的结构清晰了。

    async 关键字表明Third_Click 是一个异步方法,这代表在方法中可以使用awaitwait 一个task

    await 关键字代表等待task 的结束。

    这段代码明显的表达了,在等待method1执行,接着等待method2执行,最后等待method3执行。

    如果想要让method1 method2 并行执行,method3 等待method1method2 结束后才开始执行,那么又该如何呢?

    横线代表方法的执行。

    clip_image006

    image

    使用TaskEx.WhenAll 方法,让method1method2 并行执行,使用await来等待任务的结果,

    最后执行method3.

    Method2 method1 并行,两者结束后执行method3.

    如果想让执行顺序变为method1 执行完后,method2method3并行执行,那么该怎么办呢?

    clip_image010

    代码如下:

    image 

    在这里使用Task.Factory.FromAsync得到一个task,接着await 这个task 得到method1执行的结果。

    后面正常的调用就可以了。

    默认弹出的是method1,method2,method3.如果将method2 sleep时间变成Thread.Sleep(500).那么弹出的就是method1,method3,method2 了。

    如果想等到所有结果后再弹出消息的话,那又该如何呢?:

    image

    clip_image016

    最后出一道题目:

    下面的代码

    private void Third_Click(object sender, RoutedEventArgs e)

    {

        IService1 service1 = new Service1Client();

        StringBuilder builder = new StringBuilder();

        Task t = Task.Factory.FromAsync(service1.BeginMethod1(null, null),

                    (ar1) =>

                    {

                        builder.Append(service1.EndMethod1(ar1));

                    });

        MessageBox.Show(

            string.Format("{0},{1}", t.IsCompleted.ToString(), builder.ToString()));

    }

    弹出的消息是:

    clip_image018

    如何修改代码让弹出来的结果是这样子呢?,请使用async,await完成。

    clip_image020

  • 相关阅读:
    JZOJ 4043. 【雅礼集训2015Kzf】洪水
    JZOJ 5451.Genocide
    P4719 【模板】"动态 DP"&动态树分治
    [NOIP2018 提高组] 保卫王国
    【NOIP2017提高组正式赛】列队
    vuex的总结
    height:100vh
    从URL输入到页面展现到底发生什么
    JS的空数组是true还是false(内附JS类型转换表)
    Vue拼图验证组件使用教程
  • 原文地址:https://www.cnblogs.com/LoveJenny/p/2399770.html
Copyright © 2011-2022 走看看