[筆記]如何將傳統的回調函數轉換爲C#5.0支持的await格式

C#5.0引入了編譯器支持的 async 和 await 關鍵字,這就爲開發者提供了使用同步思想寫異步代碼的方便。異步

可是有些傳統函數僅提供了異步回調實現,如何對其封裝,使其能夠享受await的便利呢?async

舉例來講,Windows Phone SDK 提供的 Contacts.SearchAsync() 函數,須要經過Delegate來處理Contacts.SearchAsync事件。函數

舉個Windows Phone 8裏面搜索聯繫人的代碼以下:spa

void Contacts_SearchCompleted(object sender, ContactsSearchEventArgs e) {
    try {
        Debug.WriteLine(e.Results.Count());
    }
    catch (Exception ex) {
        Debug.WriteLine(ex.ToString());
    }
}

private void btnSearchContacts_Click(object sender, RoutedEventArgs e) {
    Contacts cons = new Contacts();
    cons.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(Contacts_SearchCompleted);
    cons.SearchAsync("", FilterKind.None, "Contacts Test");
}

不是說這種回調方式很差,而是我認爲下面這種使用await的方式調用會更好。code

async private Task<IEnumerable<Contact>> SearchContacts(string filter, FilterKind filterKind, Object state) {
    return await Task<IEnumerable<Contact>>.Run(
        () => {
            Debug.WriteLine("SearchContacts begin");

            var signal = new ManualResetEvent(false);
            IEnumerable<Contact> ret = null;

            Contacts cons = new Contacts();
            cons.SearchCompleted += (o, e) => {
                Debug.WriteLine("SearchContacts complete");
                ret = e.Results;
                signal.Set();
            };
            cons.SearchAsync(filter, filterKind, state);
            signal.WaitOne();
            signal.Dispose();
            Debug.WriteLine("SearchContacts end");
            return ret;
        }
        );
}

async private void btnSearchContactsAwait_Click(object sender, RoutedEventArgs e) {
    IEnumerable<Contact> cons = await SearchContacts("", FilterKind.None, "Contacts Test");
    Debug.WriteLine(cons.Count());
}

將代碼包裝在Task裏面,經過ManualResetEvent來控制代碼流程,用起來超屌的。blog

相關文章
相關標籤/搜索