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

來源:互聯網
上載者:User

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

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.