.net 4.5已经发布很久了,但是一直也没有静下心来好好的研究微软给开发者带来的喜悦。
今天我将简单的介绍下 async + await 这对搭档的出现,如何让频繁假死的界面飞起来(其实只是不再阻塞UI线程而已,标题党一下)
建议大家先了解下 IAsyncReuslt ,做过异步的应该都知道它怎么用吧?用过socket的人也几乎对它了如指掌了,不知道的谷歌一下吧,我就不贴上来了。
园子里“滴答的雨”已经详细解释过了,我这里只贴一个例子以便跟我写的方式进行对比。
其中 for 循环是为了增加网络延迟,模拟一定的加载时间而已,网速好的同学可以自行放宽。
private async void button1_Click(object sender, EventArgs e) { string s = await Test(); MessageBox.Show(s); } private async Task<string> Test() { string str = null; for (int i = 0; i < 10; i++) { using (WebClient wc = new WebClient()) { str = await wc.DownloadStringTaskAsync("http://www.baidu.com"); } } return str; }
现在我想让我的代码变成这个样子,尽量少的改动之前的函数,同时新写的方法也不需要考虑返回Task<T>
其实区别在于两点:
1. await new FastAsync<string>().TaskAsync();
2.TestAsync 函数本身没有引用到 async 或者 await ,也就是说逻辑函数相比较之前的版本来说没有做出改动。
private async void button1_Click(object sender, EventArgs e) { string s = await new FastAsync<string>().TaskAsync(TestAsync); MessageBox.Show(s); } private string TestAsync() { string str = null; for (int i = 0; i < 10; i++) { using (WebClient wc = new WebClient()) { str = wc.DownloadString("http://www.baidu.com"); } } return str; }
通过上面的代码应该已经发现问题了,就是 FastAsync<string> 是哪里来的呢?这就是今天要说的重点了。代码量不多,只没特别的技术含量只是需要动下脑而已。
public class FastAsync<T> { TaskCompletionSource<T> m_tcs; public Task<T> TaskAsync(Func<T> func) { m_tcs = new TaskCompletionSource<T>(); IAsyncResult result = func.BeginInvoke(new AsyncCallback(AsyncResult), func); return m_tcs.Task; } private void AsyncResult(IAsyncResult result) { Func<T> func = result.AsyncState as Func<T>; T entity = func.EndInvoke(result); m_tcs.SetResult(entity); } }
是不是很简单?
或许大家有更好的方法,欢迎交流,本文的实现方式只是我一时兴起想出来的,目的也很简单,就是想简化代码。
当然,这也未必是最简单的实现方式,在这里我只能说我提供的是一个思路,一个简化版实现方式而已,真实项目中还要继续改进和扩展。如果您喜欢,麻烦点个赞?哈哈^_^