.NET Core多线程通关 (2) 异步

大家好
去年换工作时系统复习了一下.NET Core多线程相关专题,学习了一线码农老哥的《.NET 5多线程编程实战》课程,我将复习的知识进行了总结形成本专题。
理解异步的本质
时间片切换成本高!
CPU密集型操作:编码解码、图形计算、正则表达式等
IO密集型操作:和硬件打交道,和DB打交道等
线程太多的烦恼/代价:
新开Thread是有开销的(时间、空间)
GC回收会冻结所有线程寻找引用根(gcroot)
Thread会和网络驱动程序打交道(外网络地址)
ThreadPool中的WorkQueue任务(4000+)得不到处理
异步:async/await
程序有可能会卡死!
(3)C#如何使用异步?
workThread:
适用于CPU密集型,在WinDbg中标签为 ThreadPool Worker
IOThread:
适用于IO密集型,在WinDbg中标签为 ThreadPool Completion Port
namespace ConsoleApp3{class Program{static void Main(string[] args){GetContentLengthAsync("http://cnblogs.com");Console.WriteLine($"主线程:{Environment.CurrentManagedThreadId}, 准备退出!");Console.ReadLine();}static async Task<int> GetContentLengthAsync(string url){using (HttpClient client = new HttpClient()){var content = await client.GetStringAsync(url);Console.WriteLine($"当前线程:{Environment.CurrentManagedThreadId}, content={content.Length}");return content.Length;}}}}
初始化时将SafeHandle、ThreadPool与IO完成端口进行绑定(比如:FileStream在Init时)
(主线程)创建IO完成端口:CreateIoCompletionPort(IntPtr FileHandle, IntPtr ExistingCompletionPort, IntPtr CompletionKey, uint NumberOfConcurrentThreads)
(主线程)将消息塞到IO完成端口的Queue队列:PostQueuedCompletionStatus
(子线程)从IO完成端口的Queue队列中获取消息:GetQueuedCompletionStatus
public class IOCP{[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]public static extern SafeFileHandle CreateIoCompletionPort(IntPtr FileHandle, IntPtr ExistingCompletionPort, IntPtr CompletionKey, uint NumberOfConcurrentThreads);[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]public static extern bool GetQueuedCompletionStatus(SafeFileHandle CompletionPort,out uint lpNumberOfBytesTransferred, out IntPtr lpCompletionKey,out IntPtr lpOverlapped, uint dwMilliseconds);[DllImport("Kernel32", CharSet = CharSet.Auto)]public static extern bool PostQueuedCompletionStatus(SafeFileHandle CompletionPort, uint dwNumberOfBytesTransferred, IntPtr dwCompletionKey, IntPtr lpOverlapped);}
// 1. 创建IO完成端口var safehandle = IOCP.CreateIoCompletionPort(new IntPtr(-1), IntPtr.Zero, IntPtr.Zero, 1);var thread = new Thread(() =>{Console.WriteLine($"工作线程: {Environment.CurrentManagedThreadId} 开始获取数据...");while (true){// 3. get数据IOCP.GetQueuedCompletionStatus(safehandle, out var ipn, out var ipc, out var lop, int.MaxValue);var receiveData = Convert.ToString(GCHandle.FromIntPtr(lop).Target);Console.WriteLine($"工作线程: {Environment.CurrentManagedThreadId} 获取数据成功!{receiveData}");Thread.Sleep(1000);}});thread.Start();// 2. post 数据var data = (IntPtr)GCHandle.Alloc("hello world");IOCP.PostQueuedCompletionStatus(safehandle, 4096, IntPtr.Zero, data);Console.WriteLine($"主线程: {Environment.CurrentManagedThreadId} 塞入数据成功!");Console.ReadLine();
.NET Core多线程通关 (2) 异步
声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。



