在深入了解 Async/Await 的强大功能之前,必须对 .NET 运行时 (CLR) 及其基础组件有深入的了解。这涉及将 .NET 代码编译为 CLR,这有助于跨平台执行。为了建立这个基础,我们将探讨线程池、任务和任务计划程序等基本术语。这些知识对于编写高效且防错的代码至关重要。
.NET 运行时提供有助于无缝执行应用程序的基本服务。主要功能包括:
线程管理是 .NET 运行时中的一个关键方面,涉及各种组件(如线程计划程序、线程池、JIT 编译器、垃圾回收器和同步机制)的协调。这些元素协同工作,为执行多线程应用程序提供托管且高效的环境。
若要理解线程管理,必须了解线程池,它是 .NET 运行时的基本组件。线程池管理器负责监督线程的创建和生命周期。线程池中存在两种不同类型的池:工作线程和完成端口线程。
线程池 一些基本组件
1. 线程池管理器 =>管理线程的创建和线程的生命周期
2.线程池中有两种类型的池,一种是工作线程池**,一种是完成线程池**。
工作线程**:**
线程池中的主要实体是工作线程。
这些线程用于在应用程序中执行短期任务。
完成端口线程**:**
完成端口线程与异步 I/O 操作相关联,并与 I/O 完成端口机制结合使用。
了解它们的动态特性,包括它们的动态大小和开发人员可配置的限制,这一点至关重要。
ThreadPool.GetMinThreads(out int minWorkerThreads, out int minCompletionPortThreads);
ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxCompletionPortThreads);Console.WriteLine($"Min Worker Threads: {minWorkerThreads}");
Console.WriteLine($"Max Worker Threads: {maxWorkerThreads}");
Console.WriteLine($"Min Completion Port Threads: {minCompletionPortThreads}");
Console.WriteLine($"Max Completion Port Threads: {maxCompletionPortThreads}");This is Result of my Local setup of .net Core Application
Min Worker Threads: 8
Max Worker Threads: 32767
Min Completion Port Threads: 8
Max Completion Port Threads: 1000
线程池管理等待执行的任务队列。这些任务放置在任务队列中**,任务计划程序**负责有效地将这些任务调度到可用线程。
简洁
的任务队列:
线程池管理需要执行的任务队列。
将任务提交到线程池时,该任务将放置在任务队列中。
任务计划程序**:**
任务计划程序是负责将任务从队列计划到可用线程的组件。
它确定哪个工作线程或完成端口线程应执行特定任务。配置最小和最大池大小可进一步增强对线程分配的控制。
ThreadPool.SetMinThreads(100, 300);
ThreadPool.SetMaxThreads(1000, 500);
First argument in both functions is the number of worker threads and
second is the number of Completion port threads.
If current request equal to 1000, and developers want to create a new thread, that request
remains in queue until the thread pool is available to allocate thread.
过渡到 Async/Await 领域时,必须了解 async 关键字在 C# 方法中的作用。异步方法表示它包含一个操作,其过程耗时,具体取决于外部因素。此关键字允许使用 await 并生成状态机来管理异步流,从而在不阻塞线程的情况下促进高效处理。
async 关键字告诉编译器以特殊方式处理该方法,允许它使用 await 关键字并生成状态机来处理异步流。
async 关键字主要用于表示包含异步操作的方法,允许使用 await 关键字并发出方法返回 Task 或 Task<T> 的信号。它不直接控制运行该方法的线程,但它支持异步编程模式,从而在不阻塞线程的情况下高效处理异步操作。它允许该方法在异步等待期间将控制权交还给调用方,从而避免线程阻塞并促进更好的可伸缩性和响应能力。
async Task MyAsyncMethod()
{
// Asynchronous operations with await
}
async 关键字使开发人员能够创建具有异步操作的方法,利用 await 关键字来促进非阻塞执行。此方法允许方法在异步等待期间产生控制权,从而防止线程阻塞,从而增强了可伸缩性、响应能力和整体代码效率。
通过全面了解这些基本概念,开发人员可以利用 Async/Await 的全部功能进行稳健高效的代码开发。
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
class Program
{
static async void asyncTask()
{
Console.WriteLine($"Before await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)} ");
await Task.Delay(10000);
Console.WriteLine($"After await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
static void Main(string[] args)
{
Console.WriteLine($"Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
asyncTask();
Console.WriteLine($"After asyncTask() Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
}
Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
Before await thread is working on it CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After asyncTask() Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After await thread is working on it CurrentThreadInfo: {"ManagedThreadId":8,"IsAlive":true,"IsBackground":true,"IsThreadPoolThread":true,"Priority":2,"ThreadState":4,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":".NET ThreadPool Worker","ApartmentState":1}
在此方案中,我们有一个简单的异步方法,使用 和 with 。主要观察结果如下:asyncTask()asyncawaitTask.Delay(10000)
此方案展示了异步操作期间线程之间的无缝转换,突出了应用程序的响应能力。
using System;
using Newtonsoft.Json;
class Program
{
static async void asyncTask()
{
Console.WriteLine($"Before await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)} ");
Console.WriteLine($"After await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
static void Main(string[] args)
{
Console.WriteLine($"Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
asyncTask();
Console.WriteLine($"After asyncTask() Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
}
Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
Before await thread is working on it CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After await thread is working on it CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After asyncTask() Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
这里,仅包含同步操作,揭示了一个有趣的行为:asyncTask()
此方案强调,并非所有标记为的方法都涉及线程切换,并且没有异步操作会导致在调用线程上直接同步执行。async
using System;
using System.Threading.Tasks;
using Newtonsoft.Json;
class Program
{
static async void asyncTask()
{
Console.WriteLine($"Before await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)} ");
Task.Delay(10000);
Console.WriteLine($"After await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
static void Main(string[] args)
{
Console.WriteLine($"Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
asyncTask();
Console.WriteLine($"After asyncTask() Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
}
Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
Before await thread is working on it CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After await thread is working on it CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After asyncTask() Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
在这种情况下,缺少 中的关键字。观察结果如下:Task.Delay(10000)awaitasyncTask()
此方案强调了正确利用以实现所需的异步行为的重要性。await
using System;
using System.Threading;
using Newtonsoft.Json;
class Program
{
static async void asyncTask()
{
Console.WriteLine($"Before await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)} ");
Thread.Sleep(10000);
Console.WriteLine($"After await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
static void Main(string[] args)
{
Console.WriteLine($"Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
Thread customThread = new Thread(asyncTask);
customThread.IsBackground = true;
customThread.Start();
Console.WriteLine($"After asyncTask() Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
}
Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After asyncTask() Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
Before await thread is working on it CurrentThreadInfo: {"ManagedThreadId":10,"IsAlive":true,"IsBackground":true,"IsThreadPoolThread":false,"Priority":2,"ThreadState":4,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After await thread is working on it CurrentThreadInfo: {"ManagedThreadId":10,"IsAlive":true,"IsBackground":true,"IsThreadPoolThread":false,"Priority":2,"ThreadState":4,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
在这里,使用 to execute 创建了一个自定义线程,并引入了一个:new Thread()asyncTask()Thread.Sleep(1000)
此方案说明了与自定义线程创建相关的其他复杂性,强调了控制和开销之间的权衡。
using System;
using System.Threading;
using Newtonsoft.Json;
class Program
{
static async void asyncTask()
{
Console.WriteLine($"Before await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)} ");
Thread.Sleep(10000);
Console.WriteLine($"After await thread is working on it CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
static void Main(string[] args)
{
Console.WriteLine($"Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
Thread customThread = new Thread(asyncTask);
customThread.Start();
Thread.Sleep(1000);
Console.WriteLine($"After asyncTask() Thread is running CurrentThreadInfo: {JsonConvert.SerializeObject(Thread.CurrentThread)}");
}
}
Before asyncTask() method called the Main Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
Before await thread is working on it CurrentThreadInfo: {"ManagedThreadId":12,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After asyncTask() Thread is running CurrentThreadInfo: {"ManagedThreadId":1,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
After await thread is working on it CurrentThreadInfo: {"ManagedThreadId":12,"IsAlive":true,"IsBackground":false,"IsThreadPoolThread":false,"Priority":2,"ThreadState":0,"CurrentCulture":"en-IN","CurrentUICulture":"en-US","ExecutionContext":{},"Name":null,"ApartmentState":1}
在最后一种情况下,自定义线程在主线程短暂休眠时运行:asyncTask()
此方案突出了并行执行的潜力,以及了解并发环境中多个线程之间的相互作用的重要性。
总之,这些方案提供了对各种异步方案中线程行为的见解,帮助开发人员了解 C# 应用程序中多线程的复杂性。