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

来源:互联网 发布:cdo 首席数据官 编辑:程序博客网 时间:2024/06/06 10:47

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


<script type="text/javascript"><!--google_ad_client = "ca-pub-1944176156128447";/* cnblogs 首页横幅 */google_ad_slot = "5419468456";google_ad_width = 728;google_ad_height = 90;//--></script><script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js"></script>