Windows 8 系列(七):使用異步API:await 和 async


Windows 8 Metro 編程相對於Windows phone 和 Silverlight 最大的不同點之一就是大量的使用了異步API,而且這些API通常沒有相對應的同步API,因此我們需要確保了解如何在Metro風格應用中使用異步API。

 

使用異步API時不可避免的會碰到兩個關鍵詞:await 和 async,下面我們舉例說明異步API的優勢和具體的用法。

異步的API一般是需要較長時間才能返回結果或者完成的(例如:I.O.操作)。假設我們在點擊一個Button之后,程序會讀取一個比較大的本地文件。

1. 如果用同步的方式讀取,那么在返回讀取結果之前的這段時間內,你得程序不能同時進行其他相應,比如用戶再次的點擊,也就是說你得程序是阻塞狀態。

2. 如果換成異步操作就不同了,程序在執行到這一行代碼時,應用會臨時退出時間處理程序,它可以在等待返回結果的過程中同時處理其他的用戶相應,直到成功返回結果后繼續進行下面的代碼。

 (經Damon.Tian提醒,這里代碼做了修改,返回類型應為Task<bool>)

private async Task<bool> IsSuccess (string fileName, StorageFolder folder)
{
    var file = await folder.CreateFileAsync(fileName,  CreationCollisionOption.OpenIfExists);

    string tempString = "Wow!";
    

return true; }

這就是讀取文件的API,在這里使用的await關鍵字,代表調用異步接口並等待返回結果后才執行后面的代碼(記住這句話,后面會講到)

再看看這個函數在定義時用了一個關鍵字:async,這是因為在此函數中至少有一個地方用了await關鍵字,那么這個函數就必須定義為async。在外面調用這個函數的時候也就可以用await關鍵字了,例如:

bool result = await IsSuccess(fileName, folder);

同樣的,上面這行代碼所在的函數,也必須聲明async關鍵字。

 

接下來,問題來了,這兩個關鍵字是不是必須要寫的呢?可不可以不用?答案是,可以。

如果在調用異步API時沒有用到await關鍵字,也是可以的。

我們還拿上面的function舉例,如果寫成下面這樣也是可以的,但是在編譯的時候會生成一個警告:沒有用await關鍵字。

var file = folder.CreateFileAsync(fileName,  CreationCollisionOption.OpenIfExists);

 

那這兩種寫法有什么不同呢?答案是:代碼的執行順序有了改變,而且返回結果的類型也變了

如果調用異步API時沒有用await,那么在執行異步操作的時候,程序是不會等待API返回結果再執行下面的代碼,而是直接執行下面的代碼:

也就是說,如果代碼變成下面這個樣子,那么file還沒有被成功賦值時(CreateFileAsync函數還未返回結果時),tempString就已經被賦值了。

 (如果不帶await 這里返回的file不再是StorageFile類型而是 IAsyncOperation<StorageFile>類型)

private async Task<bool> IsSuccess (string fileName, StorageFolder folder)
{
    var file = folder.CreateFileAsync(fileName,  CreationCollisionOption.OpenIfExists);

    string tempString = "Wow!";
    

return true; }

 

 

例如:應用中一般都會有彈出框彈出警告,例如:假設我們寫一個demo,發布博文成功后用彈出系統警告框,下面是公共函數:彈出系統警告框

 

 

public async static void Alert(string message, string title = "")
        {
            MessageDialog dlg = new MessageDialog(message, title);
            await dlg.ShowAsync();
        }

 

 

代碼一:

Alert("您還未登陸。");
Alert("請登錄!");

 

 

代碼二:

await Alert("您還未登陸。");
await Alert("請登錄!");

 

 

以上兩段代碼執行的結果不同,第一段代碼會連續彈出兩個彈出框,先彈出“您還未登錄。”,然后彈出“請登錄!”,第二個彈出框在第一個彈出框的上面。

代碼二會先彈出第一個警告:未登錄,用戶點擊“確定”按鈕關閉彈出框后,才會彈出第二個彈出框。

 

另外需要注意的是:

await無法用在類似lock塊代碼中

 

lock(tempString)
{
       //這里不能用await
}

 

 Lamda表達式可以這樣寫

this.Loaded += async (sender, args) => 
{
await ...
};

 

以上是我的個人簡介,有任何問題或不同建議,歡迎提出,大家一起討論,更好的鋪平win8開發之路!

 

 

我的微博:http://weibo.com/345169632 介是為什么

我的博客:http://www.cnblogs.com/lihaiyin


免責聲明!

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



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