美文网首页
不异步,仅使用Task,使用Task+Async,Await,三

不异步,仅使用Task,使用Task+Async,Await,三

作者: 小狼在IT | 来源:发表于2018-04-23 10:34 被阅读0次

    先看看不使用Async,Await:

         //创建计时器
         private static readonly Stopwatch Watch = new Stopwatch();
    
         private static void Main(string[] args)
         {
             test2();
         }
    
         //不使用Async、Await的同步
         private static void test2()
         {
             Watch.Start();
             const string url1 = "http://www.cnblogs.com/";
             const string url2 = "https://www.csdn.net/";
             //也可以这样   Task<int> t = Task.Factory.StartNew<int>(() => CountCharacters(1, url1));
             Task<int> t1 = new Task<int>(() => CountCharacters(1, url1));
             t1.Start();
             Task<int> t2 = new Task<int>(() => CountCharacters(1, url2));
             t2.Start();
             for (var i = 0; i < 3; i++)
             {
                 ExtraOperation(i + 1);
             }
             //控制台输出
             Console.WriteLine("{" + url1 + "} 的字符个数:{" + t1.Result + "}");
             Console.WriteLine("{" + url2 + "} 的字符个数:{" + t2.Result + "}");
           
             Console.WriteLine("全部执行完成,使用时间:{" + Watch.ElapsedMilliseconds + "} ms");
             Console.Read();
         }
    
         //同步
         private static void test1()
         {
             //启动计时器
             Watch.Start();
    
             const string url1 = "http://www.cnblogs.com/";
             const string url2 = "https://www.csdn.net/";
    
             //两次调用 CountCharacters 方法(下载某网站内容,并统计字符的个数)
             var result1 = CountCharacters(1, url1);
             var result2 = CountCharacters(2, url2);
    
             //三次调用 ExtraOperation 方法(主要是通过拼接字符串达到耗时操作)
             for (var i = 0; i < 3; i++)
             {
                 ExtraOperation(i + 1);
             }
    
             //控制台输出
             Console.WriteLine("{" + url1 + "} 的字符个数:{" + result1 + "}");
             Console.WriteLine("{" + url2 + "} 的字符个数:{" + result2 + "}");
             Console.WriteLine("全部执行完成,使用时间:{" + Watch.ElapsedMilliseconds + "} ms");
             Console.Read();
         }
    
         /// <summary>
         /// 统计字符个数
         /// </summary>
         /// <param name="id"></param>
         /// <param name="address"></param>
         /// <returns></returns>
         private static int CountCharacters(int id, string address)
         {
             var wc = new WebClient();
             Console.WriteLine("开始调用 id = {"+id+"}:{"+Watch.ElapsedMilliseconds+"} ms");
    
             var result = wc.DownloadString(address);
             Console.WriteLine("调用完成 id = {"+id+"}:{"+Watch.ElapsedMilliseconds+"} ms");
    
             return result.Length;
         }
    
         /// <summary>
         /// 额外操作
         /// </summary>
         /// <param name="id"></param>
         private static void ExtraOperation(int id)
         {
             //这里是通过拼接字符串进行一些相对耗时的操作
             var s = "";
    
             for (var i = 0; i < 6000; i++)
             {
                 s += i;
             }
    
             Console.WriteLine("id = {" + id + "} 的 ExtraOperation 方法完成:{" + Watch.ElapsedMilliseconds + "} ms");
         }
    

    当执行test1()时,结果是:


    image.png

    当执行test2()时,结果是:


    image.png

    可以看出在调用CountCharacters方法时,若使用了new Task<int>(...)的方式去调用,达到了异步的效果。整个程序运行速度明显加快。程序主线程在需要CountCharacters的返回值的地方会阻塞程序,等待CountCharacters执行完成。

    再改一下代码,使用Async、Await的方式:

    class Program
    {
        //创建计时器
        private static readonly Stopwatch Watch = new Stopwatch();
    
        private static void Main(string[] args)
        {
            //启动计时器
            Watch.Start();
    
            const string url1 = "http://www.cnblogs.com/";
            const string url2 = "https://www.csdn.net/";
    
            //两次调用 CountCharacters 方法(下载某网站内容,并统计字符的个数)
            var result1 = CountCharacters(1, url1);
            var result2 = CountCharacters(2, url2);
    
            //三次调用 ExtraOperation 方法(主要是通过拼接字符串达到耗时操作)
            for (var i = 0; i < 3; i++)
            {
                ExtraOperation(i + 1);
            }
    
            //控制台输出
            Console.WriteLine("{" + url1 + "} 的字符个数:{" + result1.Result + "}");
            Console.WriteLine("{" + url2 + "} 的字符个数:{" + result2.Result + "}");
            Console.WriteLine("全部执行完成,使用时间:{" + Watch.ElapsedMilliseconds + "} ms");
            Console.Read();
        }
    
        /// <summary>
        /// 统计字符个数
        /// </summary>
        /// <param name="id"></param>
        /// <param name="address"></param>
        /// <returns></returns>
        private static async Task<int> CountCharacters(int id, string address)
        {
            var wc = new WebClient();
            Console.WriteLine("开始调用 id = {" + id + "}:{" + Watch.ElapsedMilliseconds + "} ms");
    
            var result = await wc.DownloadStringTaskAsync(address);
            Console.WriteLine("调用完成 id = {" + id + "}:{" + Watch.ElapsedMilliseconds + "} ms");
    
            return result.Length;
        }
    
        /// <summary>
        /// 额外操作
        /// </summary>
        /// <param name="id"></param>
        private static void ExtraOperation(int id)
        {
            //这里是通过拼接字符串进行一些相对耗时的操作
            var s = "";
    
            for (var i = 0; i < 6000; i++)
            {
                s += i;
            }
    
            Console.WriteLine("id = {" + id + "} 的 ExtraOperation 方法完成:{" + Watch.ElapsedMilliseconds + "} ms");
        }
    }
    

    执行结果:


    image.png

    从结果来看,用了Task,速度确实是快了很多。大部分有返回值的方法,都可以考虑改成这样的方式去做。
    而用不用Async、Await实际上区别不大。只是Async、Await有点语法糖的意思。
    如果公司用的是VS2010这样的旧型IDE,或者你想写个方法,既能用于同步,又能用于异步的,那就不加Async、Await;
    如果基本确定,就是要玩异步的,那就用Async、Await,看起来也挺直观。

    参考:http://www.cnblogs.com/liqingwen/p/6640861.html

    相关文章

      网友评论

          本文标题:不异步,仅使用Task,使用Task+Async,Await,三

          本文链接:https://www.haomeiwen.com/subject/ytrklftx.html