使用C#进行异步Web请求

6

你好,我有一个函数,用于将URL GET参数传递给Web服务器上的PHP文件,并等待文件的响应(通常需要10-20秒)。我想将其放在循环中,因为我必须同时向大约5个不同的PHP文件发送这些GET请求,但是当我尝试将其添加到循环中时,该函数会使循环等待文件返回响应,然后才会继续下一个。

    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个请求而不必等待前一个请求完成?(我在考虑多线程,但是我以前从未接触过,不知道从哪里开始。)

1
线程是解决这个问题的方法,不过在继续之前你需要等待所有5个线程都回复。 - ChrisF
4个回答

9

这里有两种使用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);
                });
}

即使 @linuxuser27 的答案没有任何错误,这个答案更好地回答了问题,并且实现起来会更容易。 - Arseni Mourzenko
+1 的确如此。 ContinueWith() 方法是个好主意。 - linuxuser27
如果我需要使用BeginGetRequestStream / EndGetRequestSteam发送一些数据的HTTP POST请求,这会如何改变呢?https://dev59.com/IW855IYBdhLWcg3wsWv3 - Konstantin Tarkus

9

您可以使用BeginGetResponse()方法,而不是GetResponse()方法,它是一种非阻塞调用。该方法需要一个回调函数来处理最终返回的WebResponse对象。链接中的示例将帮助您了解如何使主线程等待所有响应返回。


1

0

使用异步方法与WebClient

Begin\End 更难使用。


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