简体   繁体   中英

Handling exceptions while getting data when its possible

Below is the code I am using to retrieve data from several urls. For couple of urls I get exception but for all others I do get valid data. Problem is that with apporoach below, I am not able to collect data for threads that were able to retrieve data without any issue. Is there anyway to collect as much url response while also knowing which urls throw exceptions?

static void Main(string[] args)
{
    var URLsToProcess = new List<string>
            {
                "http://www.microsoft.com",
                "http://www.stackoverflow.com",
                "http://www.google.com",
                "http://www.apple.com",
                "http://www.ebay.com",
                "http://www.oracle.com",
                "http://www.gmail.com",
                "http://www.amazon.com",
                "http://www.outlook.com",
                "http://www.yahoo.com",
                "http://www.amazon124.com",
                "http://www.msn.com"
                };

    string[] tURLs = null;
    try
    {
        tURLs = URLsToProcess
            .AsParallel()
            .WithDegreeOfParallelism(3)
            .Select(uri => DownloadStringAsTask(new Uri(uri)).Result)
            .ToArray();
    }
    catch (AggregateException ex)
    {
        AggregateException exf =  ex.Flatten();

    }
    Console.WriteLine("download all done");
    if (tURLs != null)
    {
        foreach (string t in tURLs)
        {
            Console.WriteLine(t);
        }
    }
}

static Task<string> DownloadStringAsTask(Uri address)
{
    TaskCompletionSource<string> tcs =
      new TaskCompletionSource<string>();
    WebClient client = new WebClient();
    client.DownloadStringCompleted += (sender, args) =>
    {
        if (args.Error != null) 
            tcs.SetException(args.Error);
        else if (args.Cancelled) 
            tcs.SetCanceled();
        else 
            tcs.SetResult(args.Result);
    };
    client.DownloadStringAsync(address);
    return tcs.Task;
}

Yes, there is:

var tasks = URLsToProcess.Select(uri => DownloadStringAsTask(new Uri(uri))).ToArray();

while (tasks.Any())
{
    try
    {
        Task.WaitAll(tasks);
        break;
    }
    catch (Exception e)
    {
        // handle exception/report progress...
        tasks = tasks.Where(t => t.Status != TaskStatus.Faulted).ToArray();
    }
}

var results = tasks.Select(t => t.Result);

Use Task.WaitAll to wait (synchronously since async-await isn't available) for all the tasks concurrently to complete. If Task.WaitAll completes successfully, break out of the while loop and extract the results using Task.Result . If there's an exception remove the faulted task and wait again for the other task and so forth.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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