第二次调用HttpWebRequest.GetRequestStream()引发了超时异常。

8

求助...我无法弄清楚为什么HttpWebRequest.GetRequestStream()会抛出超时异常...每次使用POST建立第二个(以及后续)连接时,它总是发生。基本上,我正在尝试每30秒创建一次连接。以下是相关代码:

我的主循环:

for( int i = 0; i < students.Count; i++ ) {

    Log( "Processing: " + students[i].DbID + ";" + students[i].Username + ";" + students[i].Password );

    UserConnection uc = new UserConnection( students[i] );
    uc.ParseAll();


    Log( "Done Processing: " + students[i].DbID + ";" + students[i].Username + ";" + students[i].Password );
}

来自用户连接:

public UserConnection( Student student )
{
    this.student = student;

    this.cookies = new CookieContainer();
    this.InitCookies();

    this.courses = new List<Course>();
}


private void InitCookies()
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create( baseUri );
    req.Method = "GET";
    req.CookieContainer = this.cookies;

    req.GetResponse();


}

public void ParseAll()
{
    ParseCourseInfo(); //get info for each class
    .
    .
    .
}

private void ParseCourseInfo()
{
    HtmlDocument page = GetPage( "POST", homeUri, "username=" + student.Username + "&password=" + student.Password + "&testcookies=1" );
    .
    .
    .
}

以下异常在GetPage中发生:
29/07/2012 1:04:22 PM : Exception: System.Net.WebException
Message: The operation has timed out
Source: System
Stack Trace:    at System.Net.HttpWebRequest.GetRequestStream(TransportContext& context)
   at System.Net.HttpWebRequest.GetRequestStream()
   at URCoursesParserV2.UserConnection.GetPage(String method, Uri pageUri, String queryString) in UserConnection.cs:line 167

这里是存在问题的GetPage代码:
private HtmlDocument GetPage( string method, Uri pageUri, String queryString = "" )
{
    Stream data = null;
    HttpWebResponse res = null;
    HttpWebRequest req = null;
    try {

        req = (HttpWebRequest)WebRequest.Create( pageUri );
        req.CookieContainer = this.cookies;
        req.Timeout = 1000 * 10; //10 seconds - I've also tried leaving it as default
        req.KeepAlive = false; ////I've also tried leaving it as true.

        if( method.ToUpper() == "POST" ) {
            req.Method = "POST";

            if( queryString != "" ) {
                byte[] postBytes = Encoding.UTF8.GetBytes( queryString );
                req.ContentType = "application/x-www-form-urlencoded";
                req.ContentLength = postBytes.Length;

                using( data = req.GetRequestStream() ) { //////////////EXCEPTION HERE ON SECOND ITERATION
                    data.Write( postBytes, 0, postBytes.Length );
                    data.Close();
                }
            }

        } else if( method.ToUpper() == "GET" ) {
            req.Method = "GET";

            if( queryString != "" ) {
                pageUri = new Uri( pageUri.ToString() + '?' + queryString );
            }

        } else {
            return null;
        }

        HtmlDocument page = null;
        using( res = (HttpWebResponse)req.GetResponse() ) {
            using( data = res.GetResponseStream() ) {
                page = new HtmlDocument();
                page.Load( data );
            }
        }
        return page;

    } catch(WebException e) {
        URCoursesParser.Log( e );
        return null;

    } catch( Exception e ) {
        URCoursesParser.Log( e );
        return null;

    } finally { ///data and res probably don't need to be checked here now because of 'using' blocks
        if( data != null ) {
            data.Close();
            data = null;
        }
        if( res != null ) {
            res.Close();
            res = null;
        }
        if( req != null ) {
            req.Abort();
            req = null;
        }
    }
}

有什么想法吗?!第一次迭代总是没问题的。如果我终止程序并重新启动,第一次迭代再次没有问题……始终是第二次和后续的迭代出现问题。

2个回答

29

这可能是问题的一部分:

private void InitCookies()
{
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create( baseUri );
    req.Method = "GET";
    req.CookieContainer = this.cookies;
    req.GetResponse();
}

这里你没有处理响应对象...因此它没有将连接返回到池中。

不太清楚这个方法的意图,但是你应该处理响应对象:

using (req.GetResponse()) {}

2
你太厉害了!我应该早点来这里,而不是浪费4个小时在琐事上。在这里,我只需要建立一个连接来初始化一些cookies,以便在post请求期间能够登录。 - Cailen
@Cailen:如果您稍后发送“真实”请求时仅设置它们,那么它是否会初始化cookie?也许不会... - Jon Skeet
谢谢Jon,真是个好发现。 - ajeetdl
1
再一次,Jon Skeet 拯救了这一天。 - John Demetriou
谢谢,Jon!我已经盯着这段代码两天了!非常感激。 - phil1630

1
我遇到了类似的问题,但我明确希望在等待响应之前退出方法。 我将请求的超时设置为100毫秒,这似乎对我有用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接