<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog336280.html" frameborder="0" width="336" scrolling="no" height="280"></iframe>
“ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法
编写者:郑昀@Ultrapower 20050406
其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。
最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:
因为dotNET的ThreadPool中提供了25个自由线程/CPU(可以在machine.config中修改此数字限制),所以一旦都被占用了,就会报告InvalidOperationException异常,异常提示为:
System.InvalidOperationException: There were not enough free threads in the ThreadPool object to complete the operation |
微软的Stephen Toub是这么说的:
需要知道的第一件事情是,在 Microsoft.NET Framework 1.x 版中,HttpWebRequest 从来不会发出同步请求。我这样说是什么意思呢?让我们来看一看 Shared Source CLI (SSCLI) 中为 HttpWebRequest.GetResponse 编写的代码,此处显示的代码省略了查看以前是否检索了该响应的代码和计算超时的代码:
public override WebResponse GetResponse() {
IAsyncResult asyncResult = BeginGetResponse(null, null);
return EndGetResponse(asyncResult);
}
您可以看出,HttpWebRequest.GetResponse 只是 BeginGetResponse 和 EndGetResponse 对周围的包装。它们是异步运行的,这意味着,BeginGetResponse 从中发出实际 HTTP 请求的线程不同于调用它的线程,而且在该请求完成之前,EndGetResponse 会阻塞。这样做的实际结果是,HttpWebRequest 将每个出站请求的 ThreadPool 排入工作项队列中。因此,我们知道 HttpWebRequest 使用来自 ThreadPool 的线程。
作为该问题的替代解决方案,Framework 小组实现了您正在研究的异常。在 BeginGetResponse 的最后(就在工作项被排入队列之前),使用 System.Net.Connection.IsThreadPoolLow 来查询池中有多少个可用工作线程。如果数量过少(少于 2 个),将会引发 InvalidOperationException。
好消息是,在 .NET Framework 2.0 中,用 HttpWebRequest.GetResponse 发出的同步请求是真正同步的,这样该问题就不复存在了,从而使得您可以将调用 GetResponse 的方法列入您的核心内容。不太好的消息是,您仍然会受到 1.x 版本中这一问题的困扰。一种解决方案是(正如您所指出的),显式限制已经排入队列的工作项的数量或在任何时间内在 ThreadPool 中执行的工作项的数量。要实现这一方法,需要有一种方法来跟踪当前有多少个未完成的工作项,并在达到预定界限之前,阻塞新的请求。
我们可以这么判断当前的自由线程数目:
int wt;
int ct;
int Count=0;
while(true)
{
if(Count++>20)
break;
ThreadPool.GetAvailableThreads(out wt,out ct);
if(wt
{
Thread.Sleep(1000);
continue;
}
else
break;
}
|
除了这个HttpWebRequest问题之外,别的地方也会发生此问题。
在http://support.microsoft.com/default.aspx?scid=kb;en-us;815637
微软演示了以下的程序:
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Net.Sockets;
namespace ThreadPoolException
{
class Class1
{
public static void <place w:st="on">Main</place>()
{
// Set number of threads to be created for testing.
int testThreads = 55;
for(int i=0;i<testthreads></testthreads>
{
ThreadPool.QueueUserWorkItem(new WaitCallback(PoolFunc));
}
Console.ReadLine();
}
static void PoolFunc(object state)
{
int workerThreads,completionPortThreads;
ThreadPool.GetAvailableThreads(out workerThreads,
out completionPortThreads);
Console.WriteLine("WorkerThreads: {0}, CompletionPortThreads: {1}",
workerThreads, completionPortThreads);
Thread.Sleep(10000);
string url ="http://www.msn.com";
HttpWebRequest myHttpWebRequest ;
HttpWebResponse myHttpWebResponse=null ;
// Creates an HttpWebRequest for the specified URL.
myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);
// Sends the HttpWebRequest, and waits for a response.
myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
myHttpWebResponse.Close();
}
}
}
|
程序输出如下:
WorkerThreads: 9, CompletionPortThreads: 1000
WorkerThreads: 8, CompletionPortThreads: 1000
WorkerThreads: 7, CompletionPortThreads: 1000
WorkerThreads: 6, CompletionPortThreads: 1000
WorkerThreads: 5, CompletionPortThreads: 1000
WorkerThreads: 4, CompletionPortThreads: 1000
WorkerThreads: 3, CompletionPortThreads: 1000
WorkerThreads: 2, CompletionPortThreads: 1000
WorkerThreads: 1, CompletionPortThreads: 1000
未处理的异常: System.InvalidOperationException: ThreadPool 对象中没有足够的自由
线程来完成操作。
at System.Net.HttpWebRequest.BeginGetResponse(AsyncCallback callback, Object
state)
at System.Net.HttpWebRequest.GetResponse()
at ThreadPoolException.Class1.PoolFunc(Object state) in c:/threadpoolexception/threa
dpoolexception/class1.cs:line 41
|
编写者:郑昀@Ultrapower
分享到:
相关推荐
C#dotnet同步异步SOCKET通讯和多线程总结
dotnet core 2.1 中文&英文dotnet core 2.1 中文&英文dotnet core 2.1 中文&英文dotnet core 2.1 中文&英文dotnet core 2.1 中文&英文dotnet core 2.1 中文&英文dotnet core 2.1 中文&英文
centos7 安装dotnet完整操作步骤,并用supervisord服务启动dotnet程序
DOTNET中WEB内置对象及数据传递和数据库操作_免费下载
C#_dotNet多线程教程[汇编].pdf
IIS 发布 Core Web 项目,发布后提示没有文件AspNetCoreModuleV2,这个时候需要在机器上安装dotnet-hosting、dotnet-sdk 以上两个文件时64位的。
skynet - Skynet 1M 线程微基准测试
dotNet Core 内存占用过高的解决方案dotNet Core 内存占用过高的解决方案
多线程数据采集器源码_dotnet整站程序
dotNET下开发操作WORD时使用的WORD控件 本人收藏了3年的资源 现放出 都是总结了很多系统 软件项目实施过程中的经验的 慢慢积累的
ThreadpoolTest.zip linux good
挺好的dotnet中文手册,非常适合初学者,目录如下: 第一篇 概论 第二篇 Web Form 第三篇 ADO.NET数据库编程 第四篇 应用程序 第五篇 Web Service 第七篇 高级应用
本软件是一个VS编译工具,是目前体积最小的VS编译器,支持c#、vb.net,支持winform和webform语言虽不能完全替代Visual studio,不过在没有Visual studio时,应急用下,还是不错的,此为dotNet1.1环境。 ------------...
DOTNET框架解决方案项目实训 包括报告 等 材料
Dotnet4.8高度兼容版,内含开发环境和运行环境脱机安装。
dotnet 手册值得你拥有
Vlc.DotNet-develop.zip 二次开发包SDK 请使用VS2017运行 Vlc.DotNet-develop.zip 二次开发包SDK 请使用VS2017运行 Vlc.DotNet-develop.zip 二次开发包SDK 请使用VS2017运行 Vlc.DotNet-develop.zip 二次开发包SDK ...
Ascgen dotNET
dotnet面试常见问题dotnet面试常见问题dotnet面试常见问题dotnet面试常见问题dotnet面试常见问题
dotnet框架