使用 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
相关,但这并不重要,因为BeginInvoke
和Task.Run
在后台使用相同的线程池。
【讨论】:
Asp.Net 线程池与托管线程池不同,在编程过程中要处理的资源要宝贵得多 @MrinalKamboj 我认为像 ASP.NET 线程池这样的特定事物甚至不存在。 IIS 将请求处理分派到同一个 CLR 托管线程池。当然,IIS 下池的默认值可能会有所不同,并且对于最大并发请求等还有其他配置调整,但这些对于 OP 的问题来说是微不足道的。以上是关于使用 IAsyncResult 委托函数的主要内容,如果未能解决你的问题,请参考以下文章
多线程之异步编程: 经典和最新的异步编程模型,async与await