看看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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM