如何在循环中创建异步http请求?

时间:2014-01-21 11:37:03

标签: c# asynchronous

昨天我found out如何在没有async / await的情况下创建多个异步http请求。但是今天我需要在循环中完成它:如果某些响应不满足某些条件 - 我需要更改它们的请求并再次发送这些请求。它可能会重复几次。 我试过这段代码:

do
{
    var loadingCoordinatesTasks = new List<Task<Terminal>>();
    var totalCountOfTerminals = terminalPresetNode.ChildNodes.Count;
    var uiTaskScheduler = TaskScheduler.FromCurrentSynchronizationContext();

    foreach (var terminal in terminals.Except(_terminalsWithCoordinates))
    {
        var address = terminal.GetNextAddress();
        var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + address);
        var webRequestTask = Task.Factory.FromAsync<WebResponse>(webRequest.BeginGetResponse,
                                                                 webRequest.EndGetResponse,
                                                                 terminal);
        var parsingTask = webRequestTask.ContinueWith(antecedent =>
        {
            // Parse the response
        });
        loadingCoordinatesTasks.Add(parsingTask);
    }

    Task.Factory.ContinueWhenAll(loadingCoordinatesTasks.ToArray(), antecedents =>
    {
        foreach (var antecedent in antecedents)
        {
            var terminalWithCoordinates = antecedent.Result;
            if (antecedent.Status == TaskStatus.RanToCompletion &&
                !terminalWithCoordinates.Coordinates.AreUnknown)
            {
                _terminalsWithCoordinates.Add(terminalWithCoordinates);
                _countOfProcessedTerminals++;
            }
        }
    });
} while (_countOfProcessedTerminals < totalCountOfTerminals);

但在 >每一组请求执行后,是否可以检查while 中的条件?

2 个答案:

答案 0 :(得分:0)

您可以在增加计数后执行检查:

_countOfProcessedTerminals++;
if (_countOfProcessedTerminals >= totalCountOfTerminals)
{
    break;
}

虽然_countOfProcessedTerminals是线程安全的吗?

答案 1 :(得分:0)

我设法使用递归:

public void RunAgainFailedTasks(IEnumerable<Task<Terminal>> tasks)
    {
        Task.Factory.ContinueWhenAll(tasks.ToArray(), antecedents =>
        {
            var failedTasks = new List<Task<Terminal>>();
            foreach (var antecedent in antecedents)
            {
                var terminal = antecedent.Result;
                // Previous request was failed
                if (terminal.Coordinates.AreUnknown)
                {
                    string address;
                    try
                    {
                        address = terminal.GetNextAddress();
                    }
                    catch (FormatException) // No versions more
                    {
                        continue;
                    }
                    var getCoordinatesTask = CreateGetCoordinatesTask(terminal, address);
                    failedTasks.Add(getCoordinatesTask);
                }
                else
                {
                    _terminalsWithCoordinates.Add(terminal);
                }
            }
            if (failedTasks.Any())
            {
                RunAgainFailedTasks(failedTasks);
            }
            else
            {
                // Display a map
            }
    },  CancellationToken.None,
        TaskContinuationOptions.None,
        TaskScheduler.FromCurrentSynchronizationContext());
}

private Task<Terminal> CreateGetCoordinatesTask(Terminal terminal, string address)
    {
        var webRequest = (HttpWebRequest)WebRequest.Create(GeoCoder.GeoCodeUrl + address);
        webRequest.KeepAlive = false;
        webRequest.ProtocolVersion = HttpVersion.Version10; 
        var webRequestTask = Task.Factory.FromAsync<WebResponse>(webRequest.BeginGetResponse,
                                                                webRequest.EndGetResponse,
                                                                terminal);
        var parsingTask = webRequestTask.ContinueWith(webReqTask =>
        {
            // Parse the response
        });
        return parsingTask;
    }