从并行获取第一个 Http 响应

Get first Http response from Parallel

我有 5 个URL,我想为每个发出一个 Http 请求,并等待第一个符合条件的响应。

List<string> urls; // url1, url2, ......

ParallelLoopResult result = Parallel.ForEach(urls, url=> GetTimeSlot(url));

private string GetTimeSlot(string url)
{
    HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);

    HttpWebResponse response = (HttpWebResponse)wr.GetResponse();
        string responseString = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet)).ReadToEnd();
        if (responseString.Length < 6)
            return "";   //PARALEL RESUME
        else
            return responseString;   //PARALEL ENDS
}

我只需要第一个回复。有可能使用 Parallel 还是有更好的方法?谢谢

Parallel.ForEach 可以很好地使用,特别是供您使用 case.Just 使用取消令牌停止所有其他 运行 任务。

 static void Main(string[] args)
    {
        var cts = new CancellationTokenSource();
        var _lock = new Object();
        var po = new ParallelOptions();
        po.CancellationToken = cts.Token;
        po.MaxDegreeOfParallelism = System.Environment.ProcessorCount;
        var listOfUrls = new List<string>() { "url1", "url2" };
        var responsResult = "";
        try
        {
            Parallel.ForEach(listOfUrls, po, (url) =>
            {
                po.CancellationToken.ThrowIfCancellationRequested();

                HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(url);

                HttpWebResponse response = (HttpWebResponse)wr.GetResponse();
                string responseString = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet)).ReadToEnd();

                lock (_lock)
                {
                    if (responseString.Length > 6)
                    {
                       responsResult = responseString;
                        cts.Cancel();
                    }                        
                }           

            });
        }
        catch (OperationCanceledException e)
        {
            //cancellation was requested
        }
        finally
        {
            cts.Dispose();
        }
    }

您可以使用 PLinq:

string firstResponse = urls
    .AsParallel()
    .Select(url => GetTimeSlot(url))
    .FirstOrDefault(r => ! string.IsNullOrEmpty(r))                
    ;