1.什么是异步
程序启动时,系统会在内存中创建一个新的进程,进程是构成运行程序的资源合集,
在进程内部,系统创建了一个称为线程的内核对象,它代表了真正执行的程序,
关于线程:
默认情况下,一个进程只包含一个线程,从程序开始一直执行到结束,
线程可以派生其他线程,因此在任意时刻,一个进程都可能包含不同状态的多个线程,来执行程序的不同部分,
系统为处理器执行所规划的单元是线程,不是进程,
不使用异步示例:
class MyDownload { Stopwatch sw = new Stopwatch(); public void DoRun() { const int LargeNumber = 6000000; sw.Start(); int t1 = CountCharacters(1, "http://www.miscrosoft.com"); int t2 = CountCharacters(2, "http://www.illustratedcsharp.com"); CountToALargeNumber(1, LargeNumber); CountToALargeNumber(2, LargeNumber); CountToALargeNumber(3, LargeNumber); CountToALargeNumber(4, LargeNumber); Console.WriteLine("Chars in http://www.miscrosoft.com {0}", t1); Console.WriteLine("Chars in http://www.illustratedcsharp.com {0}", t2); } private int CountCharacters(int id, string uristring) { WebClient wc1 = new WebClient(); Console.WriteLine("Starting call {0} : {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds); string result = wc1.DownloadString(new Uri(uristring)); Console.WriteLine(" Call {0} completed : {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds); return result.Length; } public 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); } }
class Program { static void Main(string[] args) { MyDownload md = new MyDownload(); md.DoRun(); Console.ReadKey(); } }
如果我们能初始化两个CountCharacter调用,无需等待结果,而是直接执行4个CountToALargeNumber调用,然后在两个CountCharacter方法调用结束后在获取结果,就可以显著的提升性能,即async/await,
class MyDownload { Stopwatch sw = new Stopwatch(); public void DoRun() { const int LargeNumber = 6000000; sw.Start(); Task<int> t1 = CountCharactersAsync(1, "http://www.miscrosoft.com"); Task<int> 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.miscrosoft.com {0}", t1.Result); Console.WriteLine("Chars in http://www.illustratedcsharp.com {0}", t2.Result); } private async Task<int> CountCharactersAsync(int id, string uristring) { WebClient wc1 = new WebClient(); Console.WriteLine("Starting call {0} : {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds); string result = await wc1.DownloadStringTaskAsync(new Uri(uristring)); Console.WriteLine(" Call {0} completed : {1, 4:N0} ms", id, sw.Elapsed.TotalMilliseconds); return result.Length; } public 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); } }
class Program { static void Main(string[] args) { MyDownload md = new MyDownload(); md.DoRun(); Console.ReadKey(); } }
这些线程都是在主线程中完成的,我们没有创建任何额外的线程,
2.asyncawait结构
如果一个程序调用某个方法,等待其执行所有处理后才继续执行,这样的方法为同步方法,
异步方法为处理完成之前就返回到调用方法,
c#的async/await特性可以创建并使用异步方法,该特性由三个部分组成,
调用方法:该方法调用异步方法,然后在异步方法执行其任务的时候继续执行,
异步方法:该方法执行异步工作,然后立即返回到调用方法,
await表达式:用于异步方法内部,指明需要异步执行的任务,一个异步方法可以包含任意多个await表达式,如果一个不包含编译器会发出警告,
调用方法如下:
class Program { static void Main(string[] args) { Task<int> value = DoAsyncStuff.CalculateSumAsync(5, 6); // 调用方法 Console.WriteLine("value:{0}", value.Result); Console.ReadKey(); } }
异步方法如下:
static class DoAsyncStuff { public static async Task<int> CalculateSumAsync(int n1, int n2) { int sum = await Task.Run(() => GetSum(n1, n2)); // 异步方法 await表达式 return sum; } private static int GetSum(int n1, int n2) { return n1 + n2; } }
3.什么是异步方法