[dotNET]“ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




ThreadPool 对象中没有足够的自由线程来完成操作”的现象和解决办法

@Ultrapower 20050406

 

其实微软有一篇《异步 HttpWebRequest、接口实现及其他》对此种现象解释得非常清楚,我这边只是做一个笔记。

最常见的就是使用HttpWebRequest的时候,调用Send方法出现这种错误,这是因为:

因为dotNETThreadPool中提供了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<5)

{

Thread.Sleep(1000);

continue;

}

else

break;

}

 

HttpWebRequesthttp://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 Main ()

            {

                // Set number of threads to be created for testing.

                int testThreads = 55;

                for(int i=0;i

                {

                    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




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值