• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            隨筆 - 55  文章 - 15  trackbacks - 0
            <2012年5月>
            293012345
            6789101112
            13141516171819
            20212223242526
            272829303112
            3456789

            常用鏈接

            留言簿

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

                 這是Windows 8 異步編程的第二部分,為什么分成兩節呢,因為,第二節確實太讓人興奮了。恰巧有篇Windows 8 開發人員博客也是這樣一個結構,題目是WinRT 和 await,之前看過,沒有什么感覺,今天試了一下,里面還是有很多需要注意的地方。

            參考文獻:
                  1. Windows 8 應用程序開發人員博客:深入探究WinRT和await:http://blogs.msdn.com/b/windowsappdev_cn/archive/2012/04/30/winrt-await.aspx 
                  2. MSDN

            因為我使用的是C++語言,所以我主要是用C++來編程,C#開發的朋友可以看參考文獻1,以下是我的理解和我覺得重要的東西。請原諒我有一部分內容是摘抄自文獻1.
            一。 基礎知識
                  我也覺得應該從基礎著手,WinRT中的所有異步功能全部源自一個接口:Windows::Foundation::IAsyncInfo

            1 public interface IAsyncInfo
            2 {
            3     AsyncStatus Status { get; }//只讀
            4     HResult ErrorCode { get; }//只讀
            5     uint Id { get; }//只讀
            6 
            7     void Cancel();
            8     void Close();
            9 }
                  所有的異步操作都應該實現此接口。但是該接口缺少了一個至關重要的功能:操作完成之后的回調函數。因此就有了下面四個接口。我想說,請大家注意每個新街口中都有一個Completed的屬性,我們可以設置這個屬性所要執行的代碼,就是我們的操作完成之后,將要執行的代碼。

            1
             public interface IAsyncAction : IAsyncInfo
             2 {
             3     AsyncActionCompletedHandler Completed { getset; }
             4     void GetResults();// void,不返回結果
             5 }
             6 
             7 public interface IAsyncOperation<TResult> : IAsyncInfo
             8 {
             9     AsyncOperationCompletedHandler<TResult> Completed { getset; }
            10     TResult GetResults();//TResult 返回結果
            11 }
            12 
            13 public interface IAsyncActionWithProgress<TProgress> : IAsyncInfo
            14 {
            15     AsyncActionWithProgressCompletedHandler<TProgress> Completed { getset; }
            16     AsyncActionProgressHandler<TProgress> Progress { getset; }//有Progress
            17     void GetResults();//void,不返回結果
            18 }
            19 
            20 public interface IAsyncOperationWithProgress<TResult, TProgress> : IAsyncInfo
            21 {
            22     AsyncOperationWithProgressCompletedHandler<TResult, TProgress> Completed { getset; }
            23     AsyncOperationProgressHandler<TResult, TProgress> Progress { getset; }//有Progress
            24     TResult GetResults();//TResult,返回結果
            25 }
                
                    暫停,我想說,C#開發人員真的很幸運,C++開發人員需要寫很久的代碼,C#只要一點點就足夠了。這是我的牢騷,請忽略。
                  那么我們還是以打開文件為例吧,上一篇文章中,我們使用了create_task這個方法,打開了文件,并且將一些內容顯示在一個OutputTextBlock中,現在我們不使用task類,只使用我們的IAsyncOperation來做。
                  好,下面是C++同學的時間,請問,你能寫出completed這個event的代碼么?并保證其運行。

            那開始吧。要知道FileOpenPicker::PickSingleFileAsync()返回的是一個Windows::Foundation::IAsyncOperation<Windows::Storage::StorageFile^>^類型的操作:
            Windows::Foundation::IAsyncOperation<Windows::Storage::StorageFile^>^ operation = openPicker->PickSingleFileAsync();//為了讓大家看清楚類型,就沒有用auto簡寫,大家用auto的話會非常簡單
                  對應上面的四個接口,顯然,返回的是第二個接口IAsyncOperation<T TResult>^操作,那么它有一個Windows::Foundation::AsyncOperationCompletedHandler<TResult>^ 類型的Completed事件,那么我們的completed就應該寫成這樣:
            operation->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<Windows::Storage::StorageFile^>(//暫時省略);
                  好復雜!
                  還沒完,繼續。AsyncOperationCompletedHandler是一個Delegate,這個Delegate其實就是原來的函數指針封裝了一下,既然是函數指針,那么肯定有參數,怎么尋找這個參數呢?把鼠標移到這個方法上,按下F12就會談到Object Browse里面去,你就會發現這個Delegate,它有一個Invoke(。。。)方法,里面就是它的參數了。
                  另外,我們沒使用+=操作符,而是使用了=,為什么呢?因為Completed是個屬性,不是個event。。。
                  回調函數的代碼段,我們用Lambda表達式來寫:
                   1 operation->Completed = ref new Windows::Foundation::AsyncOperationCompletedHandler<Windows::Storage::StorageFile^>([this](Windows::Foundation::IAsyncOperation<Windows::Storage::StorageFile^>^ asyncInfo, Windows::Foundation::AsyncStatus status) 
             2         {
             3             //這里,貌似程序會在這里執行3次,具體原理不太清楚。
             4             if(status == Windows::Foundation::AsyncStatus::Completed)
             5             {
             6                 //因為執行3次,所以我在這個里面加了一個計數器,但是最終的結果還是1,這個異步方法還是執行了一次
             7                 //這里為什么是要Dispatcher->RunAsync呢,因為,這是一個回調函數,另一個線程中了。
             8                 //可以看到,這所有的一切都可以用then或者await來代替。
             9                 this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this](){
            10                     static int i = 0;
            11                     i++;
            12                     OutputTextBlock->Text = i.ToString();
            13                 }));
            14             }
            15             //如果執行了operation->Canceled()方法會到這里
            16             else if(status == Windows::Foundation::AsyncStatus::Canceled)
            17             {
            18                 this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this](){
            19                     OutputTextBlock->Text = "Canceled";
            20                 }));
            21             }
            22             //操作出現錯誤會到這里
            23             else if(status == Windows::Foundation::AsyncStatus::Error)
            24             {
            25                 this->Dispatcher->RunAsync(Windows::UI::Core::CoreDispatcherPriority::Normal, ref new Windows::UI::Core::DispatchedHandler([this](){
            26                     OutputTextBlock->Text = "Error";
            27                 }));
            28             }
            29             //這里不能返回StorageFile^ 類型的對象,為神馬呢?因為TResult是void,如果你返回了,那么編譯器會提醒你很長一段東西,你自己就會發現了
            30             //return safe_cast<Windows::Storage::StorageFile^>(asyncInfo->GetResults());
            31         });

                  具體的內容都是上面的這段代碼了,有些東西我想再提醒一下。
            1. 首先,我們來看第30行,因為我覺得這個方法是返回一個StorageFile對象的,所以我在Lambda方法中理應返回它,但是如果返回的話,就是錯誤的,為什么?原因是這里的返回值實際上是Invoke方法的返回值,在這里這個返回值是void的,所以你不能返回任何東西。
            2. 使用asyncInfo->GetResults();可以得到你的結果,回頭看看那四個接口,有些返回TResult,有些返回void,是吧。
            3. 在這個代碼段里,我們已經跑到了另外一個線程中去了,如果你想操作UI,那么,你必須使用Dispatcher->RunAsync方法調度回UI線程,不信你可以試試。
            4. 你可以在代碼中判斷現在IAsyncOperation的狀態。


                   哦,看看C#程序員的優越性把:
            op.Completed = (info, status) =>
                        {
                            if (status == AsyncStatus.Completed)
                            {
                                SyndicationFeed feed = info.GetResults();
                                UpdateAppWithFeed(feed);
                            }
                            else if (status == AsyncStatus.Canceled)
                            {
                                // Operation canceled
                            }
                            else if (status == AsyncStatus.Error)
                            {
                                // Error occurred, Report error
                            }
                        };
                   
            希望你還能堅持。*^◎^*
                   看到這里你發現了么?這段代碼的功能其實是跟上一篇代碼的功能一模一樣,再把之前的代碼貼過來
             1 create_task(openPicker->PickSingleFileAsync()).then([this](StorageFile^ file)
             2         {
             3             if (file)
             4             {
             5                 OutputTextBlock->Text = "Picked photo: " + file->Name;
             6             }
             7             else
             8             {
             9                 OutputTextBlock->Text = "Operation cancelled.";
            10             }
            11         }).then([this](task<void> t)
            12         {
            13             try{
            14                 t.get();
            15             }catch(Platform::Exception^ e)
            16             {
            17                 OutputTextBlock->Text = e->Message
            18             }
            19         });
                
                  額,希望你能明白,task為我們做了些什么東西。我來總結一下吧:
            1. 沒有了復雜的completed回調函數,操作完成之后,執行then中的代碼,簡單而明了。
            2. then中的異步代碼是在UI線程中的,沒有Dispatcher->RunAsync方法,不是么?
            3. 可以有多個then
            4. 可以處理異常,不是更強大么?
                  task為我們做的,就是從30多行復雜的代碼精簡到只有20行。

            至于原理,大家可以閱讀參考文獻1,我暫時還沒有怎么理解。。。
            posted on 2013-01-06 16:43 Dino-Tech 閱讀(1982) 評論(0)  編輯 收藏 引用
            无码AV波多野结衣久久| 久久人人爽人人人人爽AV| 久久99国内精品自在现线| 国产91色综合久久免费分享| 久久精品视频网| 老男人久久青草av高清| 欧美777精品久久久久网| 亚洲欧美久久久久9999| 久久超乳爆乳中文字幕| 国产精品成人久久久久久久| 亚洲国产精品成人久久蜜臀 | 午夜精品久久久久久久| 狠狠干狠狠久久| 亚洲精品乱码久久久久66| 93精91精品国产综合久久香蕉 | A狠狠久久蜜臀婷色中文网| 欧美日韩中文字幕久久伊人| 久久久这里有精品| 成人a毛片久久免费播放| 久久精品人人槡人妻人人玩AV| 久久人人爽人人澡人人高潮AV| 91久久婷婷国产综合精品青草| 一级A毛片免费观看久久精品| 天天爽天天爽天天片a久久网| 色综合久久久久久久久五月| 亚洲婷婷国产精品电影人久久| 国产亚洲欧美成人久久片| 欧洲成人午夜精品无码区久久| 久久亚洲国产成人精品无码区| 久久免费高清视频| 国产精品久久永久免费| 久久男人Av资源网站无码软件| 国产精品久久久久久五月尺| 午夜精品久久久久久影视riav| 久久综合九色欧美综合狠狠| 久久91精品综合国产首页| 久久福利青草精品资源站免费| 国产99精品久久| 色综合久久综精品| 激情综合色综合久久综合| 久久国产成人午夜AV影院|