日期:2014-06-10  浏览次数:20550 次

.net 4.5已经发布很久了,但是一直也没有静下心来好好的研究微软给开发者带来的喜悦。

今天我将简单的介绍下 async + await 这对搭档的出现,如何让频繁假死的界面飞起来(其实只是不再阻塞UI线程而已,标题党一下

 

建议大家先了解下 IAsyncReuslt ,做过异步的应该都知道它怎么用吧?用过socket的人也几乎对它了如指掌了,不知道的谷歌一下吧,我就不贴上来了。

 

  • async + await 让界面飞

   园子里“滴答的雨”已经详细解释过了,我这里只贴一个例子以便跟我写的方式进行对比。

   其中 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;
        }
  • 改造async + await的使用方式,提供快速操作函数

   通过上面的代码应该已经发现问题了,就是 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);
        }
    }

 

   是不是很简单?

   或许大家有更好的方法,欢迎交流,本文的实现方式只是我一时兴起想出来的,目的也很简单,就是想简化代码。

   当然,这也未必是最简单的实现方式,在这里我只能说我提供的是一个思路,一个简化版实现方式而已,真实项目中还要继续改进和扩展。如果您喜欢,麻烦点个赞?哈哈^_^