异步编程:
同步:按照顺序,一件事情做完了才能接着做一件事情,比如主函数中执行多个顺序方法和语句,只有上一条语句或者方法执行完毕才能执行下一个方法或者语句。
异步:开始一个任务(比如一个方法)后,让任务在另一个线程中执行,本线程可以继续执行别的事情,然后等待那个任务执行完毕
比如一个UI按钮,UI就相当于一个主函数,而按钮事件就是调用的方法,如果使用同步,那么在方法执行期间,整个ui界面就会发生阻塞,从而导致无法做任何操作
多线程和异步不是同一个概念,多线程是用于实现异步的一种方式。
异步可以用线程来实现也可以不用线程实现,C#使用线程来实现
传统方法一,异步模式,使用委托的BeginInvoke及EndInvoke
class Program { public delegate int FooDelegate(string s); static void Main(string[] args) { Console.WriteLine("主线程" + Thread.CurrentThread.ManagedThreadId); FooDelegate fooDelegate = Foo; IAsyncResult result = fooDelegate.BeginInvoke("Hello World", null, null); Console.WriteLine("主线程继续执行做其他事..."); int n = fooDelegate.EndInvoke(result); Console.WriteLine("回到主线程" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("结果是" + n); Console.ReadKey(true); } public static int Foo(string s) { Console.WriteLine("函数所在线程" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("异步线程开始执行:" + s); Thread.Sleep(1000); return s.Length; } }
传统方法二,基于事件,对于完成后打印结果等后续语句,使用委托回调
class Program_Callback { public delegate int FooDelegate(string s); static void Main(string[] args) { Console.WriteLine("主线程" + Thread.CurrentThread.ManagedThreadId); FooDelegate fooDelegate = Print; IAsyncResult result = fooDelegate.BeginInvoke("Hello World", PrintComplete, fooDelegate);//这里回调PrintComplete方法 Console.WriteLine("主线程继续执行做其他事..."); Console.ReadKey(true); } public static int Print(string s) { Console.WriteLine("函数所在线程" + Thread.CurrentThread.ManagedThreadId); Console.WriteLine("异步线程开始执行:" + s); Thread.Sleep(1000); return s.Length; } public static void PrintComplete(IAsyncResult result) { (result.AsyncState as FooDelegate).EndInvoke(result); Console.WriteLine("当前线程结束" + result.AsyncState.ToString()); } }
最新方式,基于任务,使用await和async关键字和Task类型
await 表示等待任务执行,用来调用返回任务的方法,或者阻塞等待一个任务执行完毕
async修饰一个方法,表示其中有await语句
await task相当于EndInvoke()用于阻塞等待任务线程执行完毕
class Program_awaitAndAsync { static async Task Main(string[] args) { Task<double> task = FacAsync(10); Console.WriteLine("主函数继续执行。。。"); for (int i = 0; i < 10; i++) Console.WriteLine("main"); double result = await task;//此处await对程序进行阻塞,直到task执行完毕 才会执行接下来的语句 Console.WriteLine("结果为"+result); Console.ReadKey(true); } public static Task<double> FacAsync(int n) { //Run会开启一个新的线程来执行委托的程序 return Task<double>.Run(() => { double s = 1; for (int i = 1; i < n; i++) { s = s + i; Console.WriteLine("task"); } return s; }); } async void Test() { double result = await FacAsync(10); Console.WriteLine(result); } }