[笔记]如何将传统的回调函数转换为C#5.0支持的await格式

C#5.0引入了编译器支持的 async 和 await 关键字,这就为开发者提供了使用同步思想写异步代码的方便。

但是有些传统函数仅提供了异步回调实现,如何对其封装,使其可以享受await的便利呢?

举例来说,Windows Phone SDK 提供的 Contacts.SearchAsync() 函数,需要通过Delegate来处理Contacts.SearchAsync事件。

举个Windows Phone 8里面搜索联系人的代码如下:

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的方式调用会更好。

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来控制代码流程,用起来超屌的。

你可能感兴趣的:(wait)