在多线程环境下使用HttpWebRequest或者调用Web Service

最近使用多线程同时调用一个Web Service,总是有很多调用报超时,代码类似于下面的代码(为了简化,我把调用Web Service改为使用HttpWebRequest访问一个网址,效果时一样的):

我循环调用100次,但是总是有几十次调用报超时,具体如下:

System.Net.WebException: 操作已超时。

at System.Net.HttpWebRequest.GetResponse()

   at HttpRequestTest.HttpRequestTest.MakeWebRequest(Object obj) in g:\my documents\visual studio projects\httprequesttest\httprequesttest.cs:line 35

真的不知道为什么,难道Web Service就不能在多线程的环境下调用!

因为目前找不到原因,暂时放在首页,想向各位请教,明天就撤调,请手下留情,谢谢!

1
using System;
 2
using System.Diagnostics;
 3
using System.Net;
 4
using System.Threading;
 5

 6
namespace HttpRequestTest
 7
{
 8
    /**//// <summary>
 9
    /// Class1 的摘要说明。
10
    /// </summary>
11
    class HttpRequestTest
12
    
{
13

14
        //[STAThread]
15
        static void Main(string[] args)
16
        
{
17
            for(int i = 0; i < 100; i++ )
18
            
{
19
                ThreadPool.QueueUserWorkItem(new WaitCallback(MakeWebRequest),"http://www.163.com");
20
            }
21
            Console.ReadLine();
22
        }
23

24
        private static void MakeWebRequest (object obj)
25
        
{
26
            string url = obj as string;
27
            HttpWebResponse res = null;
28
            try
29
            
{
30
                HttpWebRequest req = (HttpWebRequest)WebRequest.Create (url);
31
                req.Timeout = 15000;
32

33
                Console.WriteLine ("\nConnecting to " + url + " 
");
34

35
                res = (HttpWebResponse)req.GetResponse ();
36

37
                Console.WriteLine("[" + AppDomain.GetCurrentThreadId() + "] ContentLength:" + res.ContentLength);
38
                Console.WriteLine ("Connected.\n");
39

40

41
            }
42
            catch (Exception e)
43
            
{
44
                Console.WriteLine ("Source : " + e.Source);
45
                Console.WriteLine ("Message : " + e.Message);
46
                Console.WriteLine(e.ToString());
47
                Debug.WriteLine(e.ToString());
48
                //Console.WriteLine("StackTrace :" + e.StackTrace);
49
            }
50
            finally
51
            
{
52
                if (res != null)
53
                
{
54
                    res.Close ();
55
                }
56
            }
57
        }
58
    }
59
}
60

多线程中调用resttemplate 多线程调用http接口_多线程中调用resttemplate




Feedback

我也碰到类似情况,也不知道怎么解决,期待答案


不知道有不有人有热情来帮你。既然我来帮你就不能嫌我话多。
1.下次你不要将你的代码加上行号,很讨厌的,这样别人没法直接copy/paste到自己的编辑器中。
2.网络是个竞争性很强的资源,在单CPU的多线程环境下15000可能是不够的,特别是很大的response并且网络带宽有限的时候。除了请求端的线程竞争还有返回端的线程竞争(返回端的线程竞争是在系统内核模态而不是在用户模态)。感觉你这样疯狂地用线程是非常不恰当的。我将次数改为20就通过了。
3.当然,你会说我篡改了你的需求,你的确要求100个并发任务。但是你必须限制你对线程的无限制使用,当线程与CPU个数之间的比例非常离谱的时候,你的CPU都是在忙于线程之间的调度了,没有时间处理你的任务。
4.其实整件事情是因为你对线程的放任使用所导致的,与HttpWebRequest或者Web Services没有任何关系。不信你可以试试任何一个长任务。不过这种情况在网络任务方面特别典型。

以下是我改过的代码:

using System; 

using System.Diagnostics; 

using System.Threading; 

using System.Net; 


namespace MultiThread 

{ 

/// <summary> 

/// Class1 的摘要说明。 

/// </summary> 

class Class1 

{ 

/// <summary> 

/// 应用程序的主入口点。 

/// </summary> 

[STAThread] 

static void Main(string[] args) 

{ 

Thread thread = new Thread(new ThreadStart(MakeThread)); 

thread.Start(); 

Console.ReadLine(); 

} 


private static int count = 30; 

private static int max = 10; 

private static int x = 0; 

private static int y = 0; 


private static void MakeThread() 

{ 

while (x < count) 

{ 

if (y < max) 

{ 

HttpWebRequest req = (HttpWebRequest)WebRequest.Create ("http://www.google.com"/); 

req.Timeout = 100000; 

ThreadPool.QueueUserWorkItem(new WaitCallback(MakeWebRequest), req); 

Interlocked.Increment(ref y); 

} 

Thread.Sleep(0); 

} 

Console.WriteLine("======================================="); 

} 


private static void MakeWebRequest (object obj) 

{ 

HttpWebRequest req = obj as HttpWebRequest; 

HttpWebResponse res = null; 

try 

{ 

Console.WriteLine ("\nConnecting to " + req.RequestUri); 

res = (HttpWebResponse) req.GetResponse (); 

Console.WriteLine("[" + AppDomain.GetCurrentThreadId() + "] ContentLength:" + res.ContentLength); 

Console.WriteLine ("Connected.\n"); 

} 

catch (Exception e) 

{ 

if (res != null) 

{ 

res.Close (); 

Interlocked.Increment(ref x); 

Interlocked.Decrement(ref y); 

res = null; 

} 

Console.WriteLine ("Source : " + e.Source); 

Console.WriteLine ("Message : " + e.Message); 

Console.WriteLine(e.ToString()); 

Debug.WriteLine(e.ToString()); 

} 

finally 

{ 

if (res != null) 

{ 

res.Close (); 

Interlocked.Increment(ref x); 

Interlocked.Decrement(ref y); 

} 

} 

} 

} 

}

类似的事情我也做过
有很多可能导致的因素
(1)楼上提到的线程切换的问题
(2)网络带宽的问题(你可以计算下,每个请求返回的数据量)
(3)对方web服务器有可能对同一个ip发起的连续的请求的限制,这也是防止网络攻击的通用做法。具体的内容我不清楚,我之前做过测试,有些web服务器好象总是同时只能接受两个请求,要等response发出之后,才能接受同一个ip的下一个请求