异步编程(基础)
1.异步编程并不是多线程
2.异步编程只是在IO操作/CPU操作 将主线程切换出去执行其他操作,不阻塞主线程,从而提升系统并发性能
3.异步并不能提升程序本身运行速度,只是能在同一时间点处理更多的任务。
举个烧水的例子(如图):
上图说明。从开始烧水到水开 不管同步还是异步,时间是相同的,只是人(主线程)在中途可以做更多的事情。
线程的切片也是需要开销,如果当前没有别的事情,只是烧水,还有必要异步吗?你觉得呢?
c#异步编程语法
异步编程方法用 async 修饰
1.返回值一般是Task
2.方法名后面标记为Async(标明该方法为异步方法)例子:HttpGetString(同步) HttpGetStringAsync(异步)
3.获取异步方法的实际返回值在调用方法前加上await 例子: string str=await HttpGetStringAsync(异步) ; 如果不加await 则返回值类型为 Task
4.await 异步非阻塞
static async Task Main(string[] args) { int result = 0; //result= GetNumAsync(99).GetAwaiter().GetResult();//不推荐 肯能会死锁 result = await GetNumAsync(99);//推荐 Console.WriteLine("Hello, World!"); } static async Task<int> GetNumAsync(int num) { int result=0; for (int i = 0; i < num; i++) { result += num; } return result; }
异步方法有什么好处?举个例子:(Winfrom程序)
public Form1() { InitializeComponent(); } //同步 private void button1_Click(object sender, EventArgs e) { Thread.Sleep(2000); this.button1.Text = this.button1.Text + "done."; } //异步 private async void button2_Click(object sender, EventArgs e) { await Task.Delay(2000); this.button2.Text = this.button2.Text + "done."; }
可以对比两个按钮点击后 是否可以拖动主窗体。 这就是主线程阻塞的一个简单例子,在Winform和WPF中经常出现界面卡死,一般是因为没有采用异步
异步编程原理:
在Await期间 系统会把当前线程返回线程池。等异步方法结束后在从线程池取出一个线程来继续执行后面的代码。
例子(获取当前线程ID):
using System.Text; {//同步 Console.WriteLine("同步Start:"+Thread.CurrentThread.ManagedThreadId); WriteText(9999); Console.WriteLine("同步End:" + Thread.CurrentThread.ManagedThreadId); } {//异步 Console.WriteLine("异步Start" + Thread.CurrentThread.ManagedThreadId); await WriteTextAsync(9999); Console.WriteLine("异步End" + Thread.CurrentThread.ManagedThreadId); } //同步 static void WriteText(int num) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < num; i++) { builder.Append("ABCDEFG"); } } //异步 static Task WriteTextAsync(int num) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < num; i++) { builder.Append("ABCDEFG"); } Console.WriteLine("异步Doing" + Thread.CurrentThread.ManagedThreadId); return File.WriteAllTextAsync("d:/1.txt",builder.ToString()); }
从上例也可以看出 异步方法里的执行并没有在新的线程中执行,而是在执行完后,由另外的线程来继续执行后面的代码。