C#图解教程(第5版) 异步编程
CountCharacters是耗时操作。发起CountCharacters的调用并且无需等待结果而是继续执行后续代码4个CountToALargeNumber调用。然后在两个耗时方法CountCharacters调用结束时再获取结果就可以显著地提升性能。1.当DoRun调用CountCharactersAsync时CountCharactersAsync将立即返回然后才真正开始下载字符。它调用方法返回的是一个Taskint类型的占位符对象表示它计划进行的工作。这个占位符最终将“返回”一个int。2.这使得DoRun不用等待实际工作完成就可继续执行。下一条语句是CountCharactersAsync的另一次调用同样会返回一个Taskint对象。3.接着DoRun可以继续执行调用4次CountToALargeNumber,同时CountCharactersAsync的两次调用继续它们的工作——基本上是等待。4.DoRun的最后两行从CountCharactersAsync调用返回的Task中获取结果。如果还没有结果将阻塞并等待。using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Net; using System.Text; using System.Threading.Tasks; namespace ConsoleApp144 { internal class Program { static void Main(string[] args) { MyDownloadString ds new MyDownloadString(); ds.DoRun(); } } } class MyDownloadString { Stopwatch sw new Stopwatch(); public void DoRun() { const int LargeNumber 6_000_000; sw.Start(); //保存结果的对象 Taskint t1 CountCharactersAsync(1, http://www.microsoft.com); Taskint t2 CountCharactersAsync(2, http://www.illustratedcsharp.com); CountToALargeNumber(1, LargeNumber); CountToALargeNumber(2, LargeNumber); CountToALargeNumber(3, LargeNumber); CountToALargeNumber(4, LargeNumber); Console.WriteLine(Chars in http://www.microsoft.com:{0}, t1.Result); Console.WriteLine(Chars in http://illustratedcsharp.com:{0}, t2.Result); } private async Taskint CountCharactersAsync(int id, string site) { WebClient wc new WebClient(); Console.WriteLine(Starting call{0}:{1,4:N0}ms, id, sw.Elapsed.TotalMilliseconds); wc.Headers.Add(HttpRequestHeader.UserAgent, Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36); wc.Headers.Add(HttpRequestHeader.Accept, text/html,application/xhtmlxml,application/xml;q0.9,image/avif,image/webp,*/*;q0.8); wc.Headers.Add(HttpRequestHeader.AcceptLanguage, zh-CN,zh;q0.9,en;q0.8); //wc.Headers.Add(HttpRequestHeader.Referer, https://www.baidu.com/); // 部分站点校验 Referer wc.Encoding Encoding.UTF8; string result await wc.DownloadStringTaskAsync(new Uri(site)); Console.WriteLine(Call{0} completed:{1,4:N0}ms, id, sw.Elapsed.TotalMilliseconds); return result.Length; } private void CountToALargeNumber(int id, int value) { for (long i 0; i value; i) ; Console.WriteLine(End counting{0}:{1,4:N0} ms, id, sw.Elapsed.TotalMilliseconds); } }同步方法运算结果4320ms异步方法运算结果3519ms异步程序比同步程序快了很多。这是由于CountToALargeNumber的4次调用是在CountCharactersAsync方法调用等待网站响应的时候进行的。所有这些工作都是在主线程中完成的我们没有创建任何额外的线程一、async/await特性的结构如果一个程序调用某个方法并在等待方法执行所有处理后才继续执行称这样的方法是同步的。异步