Use VS2017 C# 7.0 to accelerate async code

来源:互联网 发布:linux内核编译详解 编辑:程序博客网 时间:2024/06/05 03:37

Reference: 

http://www.debug.is/2015/04/17/c-sharp-vs-go/

http://www.jb51.net/article/108159.htm


Before VS2017 C# 7:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Net;


namespace newfeature
{
    public class CacheContext
    {
        public static async Task<List<DownloadResult>> DownloadUrlsAsync(string path)
        {
            var results = new List<DownloadResult>();
            List<Task<DownloadResult>> tasks = File.ReadLines(path).Select(a =>
            DownloadAsync(a)).ToList();
            while (tasks.Any())
            {
                Task<DownloadResult> task = await Task.WhenAny(tasks);
                tasks.Remove(task);
                results.Add(task.Result);
            }
            return results;
        }


        private static async Task<DownloadResult> DownloadAsync(string url)
        {
            try
            {
                //using (System.Net.WebClient client = new WebClient())
                {
                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();
                    // byte[] data = await client.DownloadDataTaskAsync(new Uri(url));
                    byte[] data = new byte[10];
                    await Task.Delay(5000);
                    stopwatch.Stop();
                    return new DownloadResult()
                    {
                        Url = url,
                        Time = stopwatch.ElapsedMilliseconds,
                        Success = true,
                        SizeInBytes = data.Length
                    };
                }
            }
            catch (Exception x)
            {
                Console.WriteLine("error downloading {0}: {1}", url, x);
                return new DownloadResult()
                {
                    Url = url,
                    Time = int.MaxValue,
                    SizeInBytes = 0,
                    Success = false
                };
            }
        }
    }
    public class DownloadResult
    {
        public string Url { get; set; }
        public long Time { get; set; }
        public bool Success { get; set; }
        public int SizeInBytes { get; set; }
    }
    class Program
    {


        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            List<DownloadResult> result = null;
            Action act = async () =>
            {
                result = await CacheContext.DownloadUrlsAsync(args[0]);
                if (result != null)
                {
                    foreach (DownloadResult r in result)
                    {
                        Console.WriteLine(r.Time + " " + r.Url);
                    }


                }


                result = await CacheContext.DownloadUrlsAsync(args[0]);
                if (result != null)
                {
                    foreach (DownloadResult r in result)
                    {
                        Console.WriteLine(r.Time + " " + r.Url);
                    }


                }
            };
            act();


            Console.Read();
        }
    }
}


After VS2017 C# 7.0:


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Net;


namespace newfeature
{
    public class CacheContext
    {
        private static Dictionary<string, DownloadResult> cache = new Dictionary<string, DownloadResult>();


        public static async Task<List<DownloadResult>> DownloadUrlsAsync(string path)
        {
            var results = new List<DownloadResult>();
            List<Task<DownloadResult>> tasks = File.ReadLines(path).Select(a =>
            CachedDownloadAsync(a).AsTask()).ToList();
            while (tasks.Any())
            {
                Task<DownloadResult> task = await Task.WhenAny(tasks);
                tasks.Remove(task);
                results.Add(task.Result);
            }
            return results;
        }


        private static ValueTask<DownloadResult> CachedDownloadAsync(string url)
        {
            lock (cache)
            {
               return cache.ContainsKey(url) ? new ValueTask<DownloadResult>(cache[url]): new ValueTask<DownloadResult> (DownloadAsync(url));
            }    
        }


        private static async Task<DownloadResult> DownloadAsync(string url)
        {
            try
            {
                //using (System.Net.WebClient client = new WebClient())
                {
                    Stopwatch stopwatch = new Stopwatch();
                    stopwatch.Start();
                    // byte[] data = await client.DownloadDataTaskAsync(new Uri(url));
                    byte[] data = new byte[10];
                    await Task.Delay(5000);
                    stopwatch.Stop();
                    DownloadResult result =  new DownloadResult()
                    {
                        Url = url,
                        Time = stopwatch.ElapsedMilliseconds,
                        Success = true,
                        SizeInBytes = data.Length
                    };
                    lock (cache)
                    {
                        cache[url] = result;
                    }
                    return result;
                }
            }
            catch (Exception x)
            {
                Console.WriteLine("error downloading {0}: {1}", url, x);
                return new DownloadResult()
                {
                    Url = url,
                    Time = int.MaxValue,
                    SizeInBytes = 0,
                    Success = false
                };
            }
        }
    }
    public class DownloadResult
    {
        public string Url { get; set; }
        public long Time { get; set; }
        public bool Success { get; set; }
        public int SizeInBytes { get; set; }
    }
    class Program
    {


        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");
            List<DownloadResult> result = null;
            Action act = async () =>
            {
                result = await CacheContext.DownloadUrlsAsync(args[0]);
                if (result != null)
                {
                    foreach (DownloadResult r in result)
                    {
                        Console.WriteLine(r.Time + " " + r.Url);
                    }


                }


                result = await CacheContext.DownloadUrlsAsync(args[0]);
                if (result != null)
                {
                    foreach (DownloadResult r in result)
                    {
                        Console.WriteLine(r.Time + " " + r.Url);
                    }


                }
            };
            act();


            Console.Read();
        }
    }
}