简体   繁体   English

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

[英]How to create async http requests in a loop?

Yesterday I've found out how to create several async http requests without async/await. 昨天,我发现了如何在不使用异步/等待的情况下创建多个异步http请求。 But today I need to do it in a loop: if some of responses don't satisfy some condition - I need to change a request for them and send these requests again. 但是今天,我需要循环执行:如果某些响应不满足某些条件-我需要更改对它们的请求,然后再次发送这些请求。 It may be repeated several times. 可能会重复几次。 I've tried this code: 我已经试过这段代码:

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);

but is it possible to check the condition in while just after every single set of requests executed? 但是是否有可能在while请求执行立即检查条件?

You can perform the check after increasing the count: 您可以在增加计数后执行检查:

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

Is _countOfProcessedTerminals thread-safe though? _countOfProcessedTerminals是否是线程安全的?

I manage to do it using recursion: 我设法使用递归来做到这一点:

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;
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM