.Net Code异步编程
程序员文章站
2024-01-03 16:01:52
...
什么是异步编程
当一个异步过程调用发出后,调用者不能立刻得到结果。基于事件机制,实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。比如,你现在要有一批数据要大数据要入库,你又不想一边入库一边等待返回结果,你可以用异步,将大数据推入一个队列,然后另外一个线程来操作这个队列里面的数据入库,入完了,就通知一下主线程。这段时间你的主线程可以做任何事。
异步编程的四种方法
一、回调函数
假定有两个函数f1和f2,后者等待前者的执行结果。如果f1是一个很耗时的任务,可以考虑改写f1,把f2写成f1的回调函数。采用这种方式,我们把同步操作变成了异步操作,f1不会堵塞程序运行,相当于先执行程序的主要逻辑,将耗时的操作推迟执行。回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,程序的流程会很混乱,而且每个任务只能指定一个回调函数。
二、事件监听
另一种思路是采用事件驱动模式。任务的执行不取决于代码的顺序,而取决于某个事件是否发生。这种方法的优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数。缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
三、发布/订阅
上一节的"事件",完全可以理解成"信号"。
四、Promises对象
Promises对象是CommonJS工作组提出的一种规范,目的是为异步编程提供统一接口。
异步编程的好处
异步的代码可以大大的提升系统的容量上限, 因为充分利用了空闲的CPU时间, 但是对于单个的请求的性能提升帮助比较有限 (除非你的单个请求大量依赖这种IO操作)
简单举例同步方法
示例:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Console.WriteLine($"头部已执行,当前主线程Id为:{Thread.CurrentThread.ManagedThreadId}");
6 string result = SayHi("jack");
7 Console.WriteLine(result);
8 Console.WriteLine($"尾部已执行,当前主线程Id为:{Thread.CurrentThread.ManagedThreadId}");
9 Console.ReadKey();
10 }
11 static string SayHi(string name)
12 {
13 Task.Delay(2000).Wait();//异步等待2s
14 Console.WriteLine($"SayHi执行,当前线程Id为:{Thread.CurrentThread.ManagedThreadId}");
15 return $"Hello,{name}";
16 }
17 }
使用async和await构建异步方法调用
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 Console.WriteLine($"头部已执行,当前主线程Id为:{Thread.CurrentThread.ManagedThreadId}");
6 CallerWithAsync("jack");
7 Console.WriteLine($"尾部已执行,当前主线程Id为:{Thread.CurrentThread.ManagedThreadId}");
8 Console.ReadKey();
9 }
10 async static void CallerWithAsync(string name)
11 {
12 Console.WriteLine($"异步调用头部执行,当前线程Id为:{Thread.CurrentThread.ManagedThreadId}");
13 string result = await SayHiAsync(name);
14 Console.WriteLine($"异步调用尾部执行,当前线程Id为:{Thread.CurrentThread.ManagedThreadId}");
15 Console.WriteLine(result);
16 }
17 static Task<string> SayHiAsync(string name)
18 {
19 return Task.Run<string>(() => { return SayHi(name); });
20 }
21 static string SayHi(string name)
22 {
23 Task.Delay(2000).Wait();//异步等待2s
24 Console.WriteLine($"SayHi执行,当前线程Id为:{Thread.CurrentThread.ManagedThreadId}");
25 return $"Hello,{name}";
26 }
27 }