Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 当一个任务被阻塞时,线程池如何使用工作线程管理工作项?_C#_.net_Windows_Clr - Fatal编程技术网

C# 当一个任务被阻塞时,线程池如何使用工作线程管理工作项?

C# 当一个任务被阻塞时,线程池如何使用工作线程管理工作项?,c#,.net,windows,clr,C#,.net,Windows,Clr,我的问题基于这篇文章 我们可以看到,对于系统中的每个线程,操作系统都会创建一个线程内核对象。操作系统使用这些线程内核对象来管理和执行整个系统中的线程 大约每20毫秒,操作系统线程调度程序就会查看就绪队列(双链接列表)中当前的所有线程内核对象。线程调度器选择一个线程内核对象并加载CPU的寄存器,其中包含上次保存在线程上下文中的值 CLR的线程池体系结构是 每个工作线程都有自己的本地队列,当工作线程调度任务时,该任务将添加到调用线程的本地队列中 在这种背景下,假设.NET线程池有一些工作线程,

我的问题基于这篇文章

我们可以看到,对于系统中的每个线程,操作系统都会创建一个线程内核对象。操作系统使用这些线程内核对象来管理和执行整个系统中的线程

大约每20毫秒,操作系统线程调度程序就会查看就绪队列(双链接列表)中当前的所有线程内核对象。线程调度器选择一个线程内核对象并加载CPU的寄存器,其中包含上次保存在线程上下文中的值

CLR的线程池体系结构是

每个工作线程都有自己的本地队列,当工作线程调度任务时,该任务将添加到调用线程的本地队列中

在这种背景下,假设.NET线程池有一些工作线程,如上图所示。假设工作线程1有一些工作项在本地队列1中排队。工作线程1执行的当前任务阻塞了几秒钟(等待信号到达等,或者它正在执行长时间运行的任务)

我的问题是,

A。工作线程1是否可以暂时停止执行此阻塞任务,并切换到其本地队列中执行另一个任务,然后在新任务完成后,再回来执行长时间运行的任务。如果是这种情况,如何保存长时间运行的任务的上下文状态?例如,我们需要将寄存器的值存储到线程内核对象1中,但当工作线程1开始执行另一个任务时,保存在线程内核对象1中的原始任务状态将丢失

B。工作线程1必须先完成此长时间运行的任务,然后才能执行其本地队列中的其他任务。但这是低效的,因为工作线程1浪费了几秒钟,它本可以用来执行其他任务

A.工作线程1是否可以暂时停止执行此阻塞任务,并切换到其本地队列中执行另一个任务,然后在新任务完成后,再回来执行长时间运行的任务。如果是这种情况,如何保存长时间运行的任务的上下文状态?例如,我们需要将寄存器的值存储到线程内核对象1中,但当工作线程1开始执行另一个任务时,保存在线程内核对象1中的原始任务状态将丢失

这实际上取决于如何执行线程1的代码

如果在线程1上以同步块的形式执行代码,则无法停止阻止任务以恢复在同一线程上的工作,除非您正在执行一些长时间运行的操作,这些操作频繁且明确地允许其他代码在同一线程上执行(见下文)

另一种方式是在C#中,您可以使用异步方法执行代码,该方法使用
await
,或者显式地允许其他代码通过使用类中的某些方法(例如/)来运行

当您使用这些方法或
await
操作符时,线程会将其剩余的时间片放弃给准备运行的具有同等优先级的任何线程。如果没有其他具有相同优先级的线程可以运行,则当前线程的执行不会挂起(除了
.Sleep()
在给定的时间范围内根本没有计划执行)

在不丢失长时间运行操作的状态的情况下,这些“时间片”被释放或挂起的方式是通过使用编译时或动态(很少)生成的已编译时间片


这些状态机将写入的代码分解成原始IL,并将其分解成不可中断的代码块,以便在调度程序分配给它运行的时间之间保持状态。

使用异步/等待。