c# - IHttpAsyncHandler 的线程

标签 c# multithreading asynchronous ihttpasynchandler

我读到this article并了解一些有关 IHttpAsyncHandler 的信息。

根据下图,当我调用 AsyncHandler 时,创建了 2 个线程。

当有请求到来时,IIS会抢一个线程——线程1来处理这个请求,当它调用beginXXX方法时,就会创建线程2来处理这个真正的逻辑。

我的问题是:

当线程2运行时,连接仍然保持,等待响应。

当线程2运行时,线程1的状态是什么?是在 sleep 吗?或者已经发布了?

如果线程1正在 sleep ,当线程2完成时,线程1被唤醒并发送响应?

如果线程1被释放,当线程2结束时,是否有一个新的线程被创建为线程1?这个新线程 1 将响应发送给客户端。

线程1和线程2在同一个线程池中,不是吗? 如果是这样,可用线程数是平衡的,这样做的目的是什么?

enter image description here

最佳答案

您并没有将线程池视为一个池。当“线程 1”在 PreRender 完成其工作时,它将返回到池中以供任何目的重用。当数据准备好时,End将从线程池中选择一个随机线程并完成其工作并发送响应。该随机线程可能是一个新线程,也可能是之前完成工作但返回到池中的同一线程。

重点是在 BeginEnd 之间的窗口中,线程已重新调整到池中,并且可以为其他连接提供服务。这允许您拥有比系统可以处理的并发线程更多的并发连接,在同步版本中,一旦达到并发线程的最大数量,您就无法再处理新请求。


让我详细介绍一下正在发生的事情

这里是两个同步连接请求的时间线,以显示为基线,为了简单起见,我们会说每个步骤都需要 1 毫秒来执行,除了 PreRender 需要 19 毫秒才能完成。

╔═══════╦════════════════════════╦══════════════════╦═════════════════╦═══════════════════╗
║ Time  ║ Action (Connection #)  ║ Open Connections ║ Running Threads ║ Available Threads ║
╠═══════╬════════════════════════╬══════════════════╬═════════════════╬═══════════════════╣
║  0 ms ║ Connection Request (1) ║                0 ║               0 ║                 2 ║
║  1 ms ║ PreInit  (1)           ║                1 ║               1 ║                 1 ║
║  2 ms ║ Init  (1)              ║                1 ║               1 ║                 1 ║
║  3 ms ║ InitComplete  (1)      ║                1 ║               1 ║                 1 ║
║  4 ms ║ PreLoad  (1)           ║                1 ║               1 ║                 1 ║
║  5 ms ║ LoadComplete  (1)      ║                1 ║               1 ║                 1 ║
║  6 ms ║ PreRender  (1)         ║                1 ║               1 ║                 1 ║
║ 10 ms ║ Connection Request (2) ║                1 ║               1 ║                 1 ║
║ 11 ms ║ PreInit  (2)           ║                2 ║               2 ║                 0 ║
║ 12 ms ║ Init  (2)              ║                2 ║               2 ║                 0 ║
║ 13 ms ║ InitComplete  (2)      ║                2 ║               2 ║                 0 ║
║ 14 ms ║ PreLoad  (2)           ║                2 ║               2 ║                 0 ║
║ 15 ms ║ LoadComplete  (2)      ║                2 ║               2 ║                 0 ║
║ 16 ms ║ PreRender  (2)         ║                2 ║               2 ║                 0 ║
║ 25 ms ║ PreRenderComplete  (1) ║                2 ║               2 ║                 0 ║
║ 26 ms ║ SaveState  (1)         ║                2 ║               2 ║                 0 ║
║ 27 ms ║ SaveStateComplete  (1) ║                2 ║               2 ║                 0 ║
║ 28 ms ║ Render  (1)            ║                2 ║               2 ║                 0 ║
║ 29 ms ║ Send Response  (1)     ║                1 ║               1 ║                 1 ║
║ 35 ms ║ PreRenderComplete  (2) ║                1 ║               1 ║                 1 ║
║ 36 ms ║ SaveState  (2)         ║                1 ║               1 ║                 1 ║
║ 37 ms ║ SaveStateComplete  (2) ║                1 ║               1 ║                 1 ║
║ 38 ms ║ Render  (2)            ║                1 ║               1 ║                 1 ║
║ 39 ms ║ Send Response  (2)     ║                0 ║               0 ║                 2 ║
╚═══════╩════════════════════════╩══════════════════╩═════════════════╩═══════════════════╝

这是异步版本的时间表。

╔═══════╦════════════════════════╦══════════════════╦═════════════════╦═══════════════════╗
║ Time  ║ Action (Connection #)  ║ Open Connections ║ Running Threads ║ Available Threads ║
╠═══════╬════════════════════════╬══════════════════╬═════════════════╬═══════════════════╣
║  0 ms ║ Connection Request (1) ║                0 ║               0 ║                 2 ║
║  1 ms ║ PreInit  (1)           ║                1 ║               1 ║                 1 ║
║  2 ms ║ Init  (1)              ║                1 ║               1 ║                 1 ║
║  3 ms ║ InitComplete  (1)      ║                1 ║               1 ║                 1 ║
║  4 ms ║ PreLoad  (1)           ║                1 ║               1 ║                 1 ║
║  5 ms ║ LoadComplete  (1)      ║                1 ║               1 ║                 1 ║
║  6 ms ║ PreRender  (1)         ║                1 ║               1 ║                 1 ║
║  7 ms ║ Begin (1)              ║                1 ║               0 ║                 2 ║
║ 10 ms ║ Connection Request (2) ║                1 ║               0 ║                 2 ║
║ 11 ms ║ PreInit  (2)           ║                2 ║               1 ║                 1 ║
║ 12 ms ║ Init  (2)              ║                2 ║               1 ║                 1 ║
║ 13 ms ║ InitComplete  (2)      ║                2 ║               1 ║                 1 ║
║ 14 ms ║ PreLoad  (2)           ║                2 ║               1 ║                 1 ║
║ 15 ms ║ LoadComplete  (2)      ║                2 ║               1 ║                 1 ║
║ 16 ms ║ PreRender  (2)         ║                2 ║               1 ║                 1 ║
║ 17 ms ║ Begin (2)              ║                2 ║               0 ║                 2 ║
║ 25 ms ║ End (1)                ║                2 ║               1 ║                 1 ║
║ 26 ms ║ PreRenderComplete  (1) ║                2 ║               1 ║                 1 ║
║ 27 ms ║ SaveState  (1)         ║                2 ║               1 ║                 1 ║
║ 28 ms ║ SaveStateComplete  (1) ║                2 ║               1 ║                 1 ║
║ 29 ms ║ Render  (1)            ║                2 ║               1 ║                 1 ║
║ 30 ms ║ Send Response  (1)     ║                1 ║               0 ║                 2 ║
║ 35 ms ║ End (2)                ║                1 ║               1 ║                 1 ║
║ 36 ms ║ PreRenderComplete  (2) ║                1 ║               1 ║                 1 ║
║ 37 ms ║ SaveState  (2)         ║                1 ║               1 ║                 1 ║
║ 38 ms ║ SaveStateComplete  (2) ║                1 ║               1 ║                 1 ║
║ 39 ms ║ Render  (2)            ║                1 ║               1 ║                 1 ║
║ 40 ms ║ Send Response  (2)     ║                0 ║               0 ║                 2 ║
╚═══════╩════════════════════════╩══════════════════╩═════════════════╩═══════════════════╝

现在,当处理两个或更少的连接时,异步并没有真正的好处,事实上,由于额外的开销,它甚至可能会稍微慢一些。

但是看看当我们有超过 2 个并发连接时会发生什么。

同步:

╔═══════╦════════════════════════╦══════════════════╦═════════════════╦═══════════════════╗
║ Time  ║ Action (Connection #)  ║ Open Connections ║ Running Threads ║ Available Threads ║
╠═══════╬════════════════════════╬══════════════════╬═════════════════╬═══════════════════╣
║  0 ms ║ Connection Request (1) ║                0 ║               0 ║                 2 ║
║  1 ms ║ PreInit  (1)           ║                1 ║               1 ║                 1 ║
║  2 ms ║ Init  (1)              ║                1 ║               1 ║                 1 ║
║  3 ms ║ InitComplete  (1)      ║                1 ║               1 ║                 1 ║
║  4 ms ║ PreLoad  (1)           ║                1 ║               1 ║                 1 ║
║  5 ms ║ LoadComplete  (1)      ║                1 ║               1 ║                 1 ║
║  6 ms ║ PreRender  (1)         ║                1 ║               1 ║                 1 ║
║ 10 ms ║ Connection Request (2) ║                1 ║               1 ║                 1 ║
║ 11 ms ║ PreInit  (2)           ║                2 ║               2 ║                 0 ║
║ 12 ms ║ Init  (2)              ║                2 ║               2 ║                 0 ║
║ 13 ms ║ InitComplete  (2)      ║                2 ║               2 ║                 0 ║
║ 14 ms ║ PreLoad  (2)           ║                2 ║               2 ║                 0 ║
║ 15 ms ║ LoadComplete  (2)      ║                2 ║               2 ║                 0 ║
║ 16 ms ║ PreRender  (2)         ║                2 ║               2 ║                 0 ║
║ 20 ms ║ Connection Request (3) ║                2 ║               2 ║                 0 ║
║ 25 ms ║ PreRenderComplete  (1) ║                2 ║               2 ║                 0 ║
║ 26 ms ║ SaveState  (1)         ║                2 ║               2 ║                 0 ║
║ 27 ms ║ SaveStateComplete  (1) ║                2 ║               2 ║                 0 ║
║ 28 ms ║ Render  (1)            ║                2 ║               2 ║                 0 ║
║ 29 ms ║ Send Response  (1)     ║                1 ║               1 ║                 1 ║
║ 30 ms ║ PreInit  (3)           ║                2 ║               2 ║                 0 ║
║ 31 ms ║ Init  (3)              ║                2 ║               2 ║                 0 ║
║ 32 ms ║ InitComplete  (3)      ║                2 ║               2 ║                 0 ║
║ 33 ms ║ PreLoad  (3)           ║                2 ║               2 ║                 0 ║
║ 34 ms ║ LoadComplete  (3)      ║                2 ║               2 ║                 0 ║
║ 35 ms ║ PreRender  (3)         ║                2 ║               2 ║                 0 ║
║ 35 ms ║ PreRenderComplete  (2) ║                2 ║               2 ║                 0 ║
║ 36 ms ║ SaveState  (2)         ║                2 ║               2 ║                 0 ║
║ 37 ms ║ SaveStateComplete  (2) ║                2 ║               2 ║                 0 ║
║ 38 ms ║ Render  (2)            ║                2 ║               2 ║                 0 ║
║ 39 ms ║ Send Response  (2)     ║                1 ║               1 ║                 1 ║
║ 54 ms ║ PreRenderComplete  (3) ║                1 ║               1 ║                 1 ║
║ 55 ms ║ SaveState  (3)         ║                1 ║               1 ║                 1 ║
║ 56 ms ║ SaveStateComplete  (3) ║                1 ║               1 ║                 1 ║
║ 57 ms ║ Render  (3)            ║                1 ║               1 ║                 1 ║
║ 58 ms ║ Send Response  (3)     ║                0 ║               0 ║                 2 ║
╚═══════╩════════════════════════╩══════════════════╩═════════════════╩═══════════════════╝

异步:

╔═══════╦════════════════════════╦══════════════════╦═════════════════╦═══════════════════╗
║ Time  ║ Action (Connection #)  ║ Open Connections ║ Running Threads ║ Available Threads ║
╠═══════╬════════════════════════╬══════════════════╬═════════════════╬═══════════════════╣
║  0 ms ║ Connection Request (1) ║                0 ║               0 ║                 2 ║
║  1 ms ║ PreInit  (1)           ║                1 ║               1 ║                 1 ║
║  2 ms ║ Init  (1)              ║                1 ║               1 ║                 1 ║
║  3 ms ║ InitComplete  (1)      ║                1 ║               1 ║                 1 ║
║  4 ms ║ PreLoad  (1)           ║                1 ║               1 ║                 1 ║
║  5 ms ║ LoadComplete  (1)      ║                1 ║               1 ║                 1 ║
║  6 ms ║ PreRender  (1)         ║                1 ║               1 ║                 1 ║
║  7 ms ║ Begin (1)              ║                1 ║               0 ║                 2 ║
║ 10 ms ║ Connection Request (2) ║                1 ║               0 ║                 2 ║
║ 11 ms ║ PreInit  (2)           ║                2 ║               1 ║                 1 ║
║ 12 ms ║ Init  (2)              ║                2 ║               1 ║                 1 ║
║ 13 ms ║ InitComplete  (2)      ║                2 ║               1 ║                 1 ║
║ 14 ms ║ PreLoad  (2)           ║                2 ║               1 ║                 1 ║
║ 15 ms ║ LoadComplete  (2)      ║                2 ║               1 ║                 1 ║
║ 16 ms ║ PreRender  (2)         ║                2 ║               1 ║                 1 ║
║ 17 ms ║ Begin (2)              ║                2 ║               0 ║                 2 ║
║ 20 ms ║ Connection Request (3) ║                3 ║               0 ║                 2 ║
║ 21 ms ║ PreInit  (3)           ║                3 ║               1 ║                 1 ║
║ 22 ms ║ Init  (3)              ║                3 ║               1 ║                 1 ║
║ 23 ms ║ InitComplete  (3)      ║                3 ║               1 ║                 1 ║
║ 24 ms ║ PreLoad  (3)           ║                3 ║               1 ║                 1 ║
║ 25 ms ║ End (1)                ║                3 ║               2 ║                 0 ║
║ 25 ms ║ LoadComplete  (3)      ║                3 ║               2 ║                 0 ║
║ 26 ms ║ PreRenderComplete  (1) ║                3 ║               2 ║                 0 ║
║ 26 ms ║ PreRender  (3)         ║                3 ║               2 ║                 0 ║
║ 27 ms ║ SaveState  (1)         ║                3 ║               2 ║                 0 ║
║ 27 ms ║ Begin (3)              ║                3 ║               1 ║                 0 ║
║ 28 ms ║ SaveStateComplete  (1) ║                3 ║               1 ║                 1 ║
║ 29 ms ║ Render  (1)            ║                3 ║               1 ║                 1 ║
║ 30 ms ║ Send Response  (1)     ║                2 ║               0 ║                 2 ║
║ 35 ms ║ End (2)                ║                2 ║               1 ║                 1 ║
║ 36 ms ║ PreRenderComplete  (2) ║                2 ║               1 ║                 1 ║
║ 37 ms ║ SaveState  (2)         ║                2 ║               1 ║                 1 ║
║ 38 ms ║ SaveStateComplete  (2) ║                2 ║               1 ║                 1 ║
║ 39 ms ║ Render  (2)            ║                2 ║               1 ║                 1 ║
║ 40 ms ║ Send Response  (2)     ║                1 ║               0 ║                 2 ║
║ 45 ms ║ End (3)                ║                1 ║               1 ║                 1 ║
║ 46 ms ║ PreRenderComplete  (3) ║                1 ║               1 ║                 1 ║
║ 47 ms ║ SaveState  (3)         ║                1 ║               1 ║                 1 ║
║ 48 ms ║ SaveStateComplete  (3) ║                1 ║               1 ║                 1 ║
║ 49 ms ║ Render  (3)            ║                1 ║               1 ║                 1 ║
║ 50 ms ║ Send Response  (3)     ║                0 ║               0 ║                 2 ║
╚═══════╩════════════════════════╩══════════════════╩═════════════════╩═══════════════════╝

请注意,在同步版本中,连接 3 在 20 毫秒后进入,但必须等到 30 毫秒后才有线程可用于处理请求。相比之下,异步版本在等待 PreRender 完成时将线程放回到池中,因此连接 3 立即能够开始处理。

因此,使用异步不会增加每秒事务数,事实上它可能会稍微降低它。然而,它所做的是增加您的“最大并发事务”计数并增加您的总吞吐量。

关于c# - IHttpAsyncHandler 的线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25141344/

相关文章:

c# - MongoDb C# 驱动程序 : mapping events to read database in cqrs solution

ios - 从解析中下载多个 (4<) PFFile 并使它们同步到正确的数组中

c# - 如何同步运行异步枚举器方法并将其存储为 IEnumerable?

C# 6.0 的新字典初始化器 - 说明

c# - Linux 上 Mono 中的 Windows kernel32 函数

c# - 编写我自己的 IScheduler 来管理线程,最好的方法是什么?

java - android.os.NetworkOnMainThreadException 如何调整在单独线程中运行的代码

java - Java 日历操作的结果不一致

android - 所有异步任务完成后如何做某事?

c# - 在自定义模型 Binder 中的模型上设置 PropertyInfo 类型的属性时执行时间长