【问题标题】:Asynchronous WebRequests using C#使用 C# 的异步 WebRequest
【发布时间】:2010-09-26 18:34:51
【问题描述】:

您好,我有一个函数可以将 url Get 参数传递给网络服务器上的 php 文件并等待来自文件的响应(通常需要 10-20 秒)。我想把它放在一个循环中,因为我必须一次将这些 Get 请求发送到大约 5 个不同的 php 文件,但是当我尝试将它添加到循环中时,该函数使循环等待文件返回响应,然后它才会去到下一个。

    public string HttpGet(string URI, string Parameters)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URI + Parameters);

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        StreamReader resStream = new StreamReader(response.GetResponseStream());
          return resStream.ReadToEnd().Trim();
    }

    private void SendCommand()
    {
        for( int i = 0; i <= 4; i++)
        {
            AddRTB(HttpGet(url, paramater));
        }
    }

有没有一种方法可以一次发送所有 5 个请求而无需等待前一个请求完成? (我正在考虑穿线它,但可惜我以前从未接触过它,我不知道从哪里开始。)

【问题讨论】:

  • 线程是解决这个问题的方法,但您需要等待所有 5 个回复才能继续。

标签: c# multithreading http-get


【解决方案1】:

您可以使用BeginGetResponse(),而不是使用GetResponse() 方法,这是一个非阻塞调用。它需要一个回调,然后当它最终返回时可以处理WebResponse 对象。链接中的示例将让您很好地了解如何让主线程等待所有响应返回。

【讨论】:

    【解决方案2】:

    这里有两种使用 TPL 的方法。

    第一个等待所有请求完成,然后再访问任何结果

    var runningTasks = new List<Task<string>>();
    
    for (int ii = 0; ii <= 4; ii++)
    {
        var wreq = (HttpWebRequest)WebRequest.Create("..." + ii);
    
        var taskResp = Task.Factory.FromAsync<WebResponse>(wreq.BeginGetResponse, 
                                                        wreq.EndGetResponse, 
                                                        null);
        var taskResult = taskResp.ContinueWith(tsk => new StreamReader(tsk.Result.GetResponseStream()).ReadToEnd().Trim());
        runningTasks.Add(taskResult);
    }
    
    Task.WaitAll(runningTasks.ToArray());
    IEnumerable<string> results = runningTasks.Select(tsk => tsk.Result);
    

    第二个对每个结果进行处理:

    for (int ii = 0; ii <= 4; ii++)
    {
        var wreq = (HttpWebRequest)WebRequest.Create("..." + ii);
    
        var taskResp = Task.Factory.FromAsync<WebResponse>(wreq.BeginGetResponse, 
                                                        wreq.EndGetResponse, 
                                                        null);
        taskResp.ContinueWith(tsk => new StreamReader(tsk.Result.GetResponseStream()).ReadToEnd().Trim())
                .ContinueWith((Task<string> trs) => 
                    { 
                        var result = trs.Result;
                        DoSomthingWithTheResult(result);
                    });
    }
    

    【讨论】:

    • +1。即使@linuxuser27 的答案没有错,这个答案更好地回答了这个问题,并且更容易实现。
    • +1 确实如此。 ContinueWith() 方法是个好主意。
    • 如果我需要使用 BeginGetRequestStream / EndGetRequestSteam 通过 HTTP POST 请求发送一些数据,这将如何改变? stackoverflow.com/questions/4190903
    【解决方案3】:

    使用请求类的 BeginGetResonse 方法代替 GetResponse。 示例和文档可以在http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx找到。

    【讨论】:

      【解决方案4】:

      将WebClient 与异步方法一起使用。

      Begin\End 比较难用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-10-09
        • 2016-03-19
        • 2016-06-25
        • 1970-01-01
        • 1970-01-01
        • 2011-05-08
        • 2010-10-13
        • 1970-01-01
        相关资源
        最近更新 更多