Асинхронные веб-запросы с использованием C # - PullRequest
6 голосов
/ 26 сентября 2010

Привет, у меня есть функция, которая передает 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 запросов одновременно, не дожидаясь завершения предыдущего? (Я думал о продвижении по ниткам, но, увы, я никогда не трогал это раньше, я не знаю, с чего начать.)

Ответы [ 4 ]

9 голосов
/ 27 сентября 2010

Вот два подхода, в которых используется 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);
                });
}
9 голосов
/ 26 сентября 2010

Вместо использования метода GetResponse() вы можете использовать BeginGetResponse(), который является неблокирующим вызовом.Он принимает обратный вызов, который может обработать объект WebResponse, когда он наконец вернется.Пример в ссылке даст вам хорошее представление о том, как заставить основной поток ждать возвращения всех ответов.

1 голос
/ 26 сентября 2010

Вместо GetResponse используйте метод BeginGetResonse класса запроса.Образец и документацию можно найти по адресу http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.begingetresponse.aspx

0 голосов
/ 26 сентября 2010

Использование WebClient с асинхронными методами.

Begin \ End более сложно использовать.

...