异步编程笔记:
场景:在一个Fun中获取用户的ID,姓名,金额.其中.用户的金额是另一个接口返回的..
同步编程步骤
Fun()
{
1. 获取用户ID,姓名 =====>假设耗时3秒
2.调用接口获取用户金额 ======>假设耗时4秒
3.组装数据,返回结果 ======>假设耗时0.1秒
}
此时该Fun()的执行时间是>=7.1秒.
异步编程步骤
Fun2()
{
1.获取用户ID,姓名 =====>假设耗时3秒
1-1:同时开启新线程获取用户金额 =====>假设耗时4秒
2.当1-1返回数据后,组装数据,返回结果. ===> 在执行Fun2()的第4~5秒时就开始执行了. ,假设耗时0.1秒
}
Fun2()的执行时间是>=4.1秒,
上面是使用场景以及不同策略给出的理论数据..下面看代码:
namespace AsyncLearn
{
class Program
{
static void Main(string[] args)
{
List<A> list = new List<A>();
Stopwatch sw = new Stopwatch();
sw.Start();
Console.WriteLine("async get money");//异步线程获取金额
var blistFun = GetMoney();
Console.WriteLine("process mainThread");//主线程逻辑设置主数据
for (int i = 0; i < 10; i++)
{
Thread.Sleep(200);
list.Add(new A
{
id = i + 1,
name = "mainThread" + i
});
}
Console.WriteLine("start set money !!!");//重点看这句打印的先后顺序
blistFun.Result.ForEach((b) => {
var item = list.FirstOrDefault(s => s.id == b.id);
if (item != null) { item.money = b.money;Console.WriteLine($"set {item.name}"); }
});
sw.Stop();
Console.WriteLine("stop set money");
Console.WriteLine("Finished " + sw.Elapsed.TotalSeconds);
Console.ReadKey();
}
static async Task<List<B>> GetMoney()
{
Console.WriteLine("start process money");
List<B> blist = new List<B>();
await Task.Run(() =>
{
for (int i = 1; i < 15; i += 2)
{
Thread.Sleep(100);//修改此处时间,观察带"!!!"的消息
blist.Add(new B
{
id = i,
money = i * 3
});
}
});
Console.WriteLine("stop process money !!!");//重点看这句打印的先后顺序
return blist;
}
}
public class A
{
public int id { get; set; }
public string name { get; set; }
public int money { get; set; }
}
public class B
{
public int id { get; set; }
public int money { get; set; }
}
}
当GetMoney接口处理速度较快时, Thread.Sleep(100);
在合并数据之前就已经完成了..
当我们把GetMoney 接口处理时间加长:Thread.Sleep(800);
此时,带"!!!"的打印位置发生变更了..
现在,我们来验证下5.64秒的代码变更成单线程执行..
1 namespace AsyncLearn
2 {
3 class Program
4 {
5 static void Main(string[] args)
6 {
7 List<A> list = new List<A>();
8 Stopwatch sw = new Stopwatch();
9 sw.Start();
10 Console.WriteLine("async get money");//异步线程获取金额
11 var blistFun =GetMoney().Result;
12 Console.WriteLine("process mainThread");//主线程逻辑设置主数据
13 for (int i = 0; i < 10; i++)
14 {
15 Thread.Sleep(200);
16 list.Add(new A
17 {
18 id = i + 1,
19 name = "mainThread" + i
20 });
21 }
22 Console.WriteLine("start set money !!!");//重点看这句打印的先后顺序
23 blistFun.ForEach((b) => {
24 var item = list.FirstOrDefault(s => s.id == b.id);
25 if (item != null) { item.money = b.money;Console.WriteLine($"set {item.name}"); }
26 });
27 sw.Stop();
28 Console.WriteLine("stop set money");
29
30 Console.WriteLine("Finished " + sw.Elapsed.TotalSeconds);
31 Console.ReadKey();
32 }
33
34 static async Task<List<B>> GetMoney()
35 {
36 Console.WriteLine("start process money");
37 List<B> blist = new List<B>();
38 await Task.Run(() =>
39 {
40 for (int i = 1; i < 15; i += 2)
41 {
42 Thread.Sleep(800);//修改此处时间,观察带"!!!"的消息
43 blist.Add(new B
44 {
45 id = i,
46 money = i * 3
47 });
48 }
49 });
50 Console.WriteLine("stop process money !!!");//重点看这句打印的先后顺序
51 return blist;
52 }
53 }
54 public class A
55 {
56 public int id { get; set; }
57 public string name { get; set; }
58
59 public int money { get; set; }
60 }
61
62 public class B
63 {
64 public int id { get; set; }
65 public int money { get; set; }
66 }
67 }
主要变化了第11行和第23行.
执行结果为:
关于异步编程的简单用法就先写到这..后期有比较好的场景,和其他用法,再来写点~ 欢迎点评~