使用 IAsyncResult 委托函数

Posted

技术标签:

【中文标题】使用 IAsyncResult 委托函数【英文标题】:Delegate Function with IAsyncResult 【发布时间】:2018-05-23 08:46:28 【问题描述】:

我的任务是接管一段使用委托的旧代码。

SearchDelegate[] dlgt = new SearchDelegate[numSearches];
IAsyncResult[] ar = new IAsyncResult[numSearches];

然后它会执行一个循环来启动多个委托函数

for (int i = 0; i < numSearches; i++)

    ar[i] = dlgt[i].BeginInvoke(....);

然后它会执行一个定时循环以从 ar 对象中获取结果。

似乎一切正常。我遇到的问题是,有时这些委托功能中的一些可能需要 3 到 4 秒才能启动,如果计数超过 10 则更长时间。这是一个常见问题,还是有我可以调整的设置?

这是在 IIS 上运行的。我可以用最少的机器资源在本地复制问题。

谢谢大家。

达兹

【问题讨论】:

【参考方案1】:

可能需要 3 到 4 秒才能启动

是由线程池引起的。当所有线程都忙时,它只会缓慢(2/秒)创建新线程。

您可以增加池中的最小线程数,但特别是对于网络应用程序,您应该广泛研究、测试和衡量这一点。 ASP.NET 也是线程池中的大股东。

【讨论】:

【参考方案2】:

BeginInvoke 方法将实际工作分派到线程池,正如它在 article 中所写的那样。当没有可用的空闲线程时,实际上可能需要一些时间。线程池可能决定等待某些工作项完成或添加额外的线程,计算最小和最大限制。

一些额外的信息可以在这里The managed threadpool和Simple description of worker and IO threads in net和本文的备注部分以及ThreadPool.SetMinThreads找到。

您应该知道,相同的线程池用于 HTTP 请求处理,因此将自定义的非 IO 绑定工作卸载到 Web 应用程序中的线程池通常是没有意义的,因为它不会给您带来任何好处并且可能由于额外的线程切换,甚至会损害性能。虽然BeginInvoke 看起来不像是异步IO 操作的调用。

实际上哪个具体线程执行工作并不重要——客户端仍然需要等待响应相同的时间。看起来,您可能会通过并行执行工作来赢得一些时间,但由于线程池中没有可用的线程来处理 HTTP 请求和您的自定义工作项,因此在负载下是不可能的。

您可能需要查看thread 以了解有关此主题的更多详细信息。它与Task 相关,但这并不重要,因为BeginInvokeTask.Run 在后台使用相同的线程池。

【讨论】:

Asp.Net 线程池与托管线程池不同,在编程过程中要处理的资源要宝贵得多 @MrinalKamboj 我认为像 ASP.NET 线程池这样的特定事物甚至不存在。 IIS 将请求处理分派到同一个 CLR 托管线程池。当然,IIS 下池的默认值可能会有所不同,并且对于最大并发请求等还有其他配置调整,但这些对于 OP 的问题来说是微不足道的。

以上是关于使用 IAsyncResult 委托函数的主要内容,如果未能解决你的问题,请参考以下文章

多线程之异步编程: 经典和最新的异步编程模型,async与await

异步使用委托delegate --- BeginInvoke和EndInvoke方法

IASyncResult接口实现简单异步编程(C#)

c# 中的线程和同步

1.初探

TcpListener的BeginAcceptTcpClient方法的两个参数是啥意思