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

news/2024/7/2 2:15:53

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





http://www.niftyadmin.cn/n/3649345.html

相关文章

Android工程师一定要知道的国内应用市场汇总

2010年在国内出现了Android系统智能机的大规模发展&#xff0c;而应用商城也在火拼起来&#xff0c;下面我推荐一下国内Android的免费软件商城。 应用汇 掌上应用汇是一款基于Android系统的本土化软件市场&#xff0c;掌上应用汇团队致力于为中国用户打造最全面&#xff0c;最…

debian 10 安装_如何在Debian 10上安装和使用ClickHouse

debian 10 安装介绍 (Introduction) ClickHouse is an open-source, column-oriented analytics database created by Yandex for OLAP and big data use cases. ClickHouse’s support for real-time query processing makes it suitable for applications that require sub-s…

虚拟机安装Kali Linux操作系统

▣ 博主主站地址&#xff1a;微笑涛声 【www.cztcms.cn】 Kali Linux是基于Debian的Linux发行版&#xff0c; 设计用于数字取证操作系统。每一季度更新一次。由Offensive Security Ltd维护和资助。最先由Offensive Security的Mati Aharoni和Devon Kearns通过重写BackTrack来完成…

指定textview中的某部分进行点击

CharSequence str"没有任何数据&#xff0c;请登录!";SpannableString spannableString1 new SpannableString(str);spannableString1.setSpan(new ClickableSpan(){Overridepublic void onClick(View widget) {Intent intentnew Intent(getActivity(),LoginActivit…

Android重力感应代码例子

android中的很多游戏的游戏都使用了重力感应的技术&#xff0c;就研究了一下重力感应 以屏幕的左下方为原点&#xff0c;箭头指向的方向为正。从-10到10&#xff0c;以浮点数为等级单位&#xff0c;想象以下情形&#xff1a; 手机屏幕向上&#xff08;z轴朝天&#xff09;水平…

react中创建一个组件_如何在React中创建社交关注组件

react中创建一个组件介绍 (Introduction) When you’re building a web site, you’ll often want to share your Social Media accounts for visitors to follow. In this tutorial, you’ll create a Social Follow component in React, using the social media icons provid…

软件框架之imageloader的使用

Imageloader的使用 一、特点&#xff1a; 1&#xff09;多线程下载图片&#xff0c;图片可以来源于网络&#xff0c;文件系统&#xff0c;项目文件夹assets中以及drawable中等 2&#xff09;支持随意的配置ImageLoader&#xff0c;例如线程池&#xff0c;图片下载器&#xff…

实验三(OSPF)7 8

解题思路&#xff1a; 先配置好路由的环回及规划好IP地址&#xff0c;确保正确&#xff1b; &#xff08;由于r8模拟为运营商&#xff0c;因此r1,r2,r3各写一条缺省指向r8 并测试&#xff09; hub-spoke网络结构&#xff0c;需要在r1-r2-r3建立隧道0配置MGRE-多点通用路由协…