(精华)2020年10月28日 Grpc Grpc双向流调用
665
2022-05-29
第一阶段
线程有限多余的会固化到磁盘
public static class Sample01 { public static void Send(IPAddress address, int port) { var tcp = new TcpClient(); try { //C10K,10K个客户端,4G,10M,上 tcp.Connect(address, port); tcp.GetStream().Write(Encoding.ASCII.GetBytes("Hello")); } catch (Exception e) { Console.WriteLine(e); throw; } finally { tcp.Close(); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
第二阶段
基于回调的异步操作
public static class Sample02 { public static void Send(IPAddress address, int port) { var client = new TcpClient(); // 开始异步连接 client.BeginConnect(address, port, ar => { // 无论成功失败都会调用这个回调 try { client.EndConnect(ar); } catch (Exception e) { Console.WriteLine(e); client.Close(); } var bytes = Encoding.ASCII.GetBytes("Hello"); var stream = client.GetStream(); stream.BeginWrite(bytes, 0, bytes.Length, result => { try { stream.EndWrite(result); } catch (Exception e) { Console.WriteLine(e); } finally { client.Close(); } },null); },null); } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
第三阶段
Task TPL 任务并行库分离了异步操作与注册回调的处理,async和await
第一种,任务中执行指定的委托(运行时内部的线程池中运行),Run和Factory.StartNew
public class TplSample { public static Task SendAsync(IPAddress address, int port) { var client = new TcpClient(); // 异步连接 var task = client.ConnectAsync(address, port); var a = new TaskFactory(); // 异步发送数据 var task1 = task.ContinueWith(t => { var bytes = Encoding.ASCII.GetBytes("Hello"); var stream = client.GetStream(); // 返回一个新的task // 这里会产生Task
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
第二种,承诺对象,Promise,将来对象,Future
public class PromiseSample { public static Task ConnectAsync(TcpClient client,IPAddress address, int port) { // 创建一个承诺对象, var promise = new TaskCompletionSource
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
task的异步
public static class ChildTaskSample { public static Task Run() { // 创建一个父任务 var parent = Task.Factory.StartNew(() => { // 创建子任务1 var child1 = Task.Factory.StartNew(() => { // 子任务1 },TaskCreationOptions.AttachedToParent); // 创建子任务2 var child2 = Task.Factory.StartNew(() => { // 子任务2 }, TaskCreationOptions.AttachedToParent); }); // 父任务会等待子任务1和2完成以后在调用回调 // 子任务中发生的异常也会传递到父任务的回调中 return parent; } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
async和await
public static class Sample06 { // async关键字是给编译器看的,我就要为生产状态机 public static async Task SendAsync(IPAddress address, int port) { var client = new TcpClient(); try { // 异步连接 await client.ConnectAsync(address, port); // 连接成功后会从这里继续开始执行 // 失败时会抛出异常并在下面的catch块中被捕捉 var bytes = Encoding.ASCII.GetBytes("Hello"); var stream = client.GetStream(); // 异步发送数据 await stream.WriteAsync(bytes, 0, bytes.Length); // 发送成功后会从这里继续开始执行 // 失败时同样会抛出异常,也在下面的catch块中被捕捉 Console.WriteLine("发送完成"); } catch (Exception e) { Console.WriteLine(e); } finally { client.Close(); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
备注:其他异步
ValueTask
从数据库随机取一条数据
先从数据库随机获取100条数据,作为将来100次调用的返回结果,每100次调用只有一次会查询数据库,其它99次都是同步完成
.NET 任务调度 多线程
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。