从并行

时间:2017-03-04 17:44:20

标签: c# parallel.foreach

我有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或有更好的方法吗?感谢。

2 个答案:

答案 0 :(得分:2)

Parallel.ForEach可以特别用于您的用例。只需使用取消令牌来停止所有其他正在运行的任务。

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

答案 1 :(得分:1)

您可以使用PLinq:

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