在可能的情况下在获取数据的同时处理异常

本文关键字:处理 异常 获取 情况下 数据 | 更新日期: 2023-09-27 18:35:43

下面是我用来从多个URL检索数据的代码。对于几个网址,我得到例外,但对于所有其他网址,我确实得到了有效的数据。问题是,使用下面的apporoach,我无法为能够毫无问题地检索数据的线程收集数据。无论如何,在知道哪些网址引发异常的同时收集尽可能多的 url 响应?

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

在可能的情况下在获取数据的同时处理异常

是的,有:

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

使用 Task.WaitAll 等待(同步,因为async-await不可用)所有任务并发完成。如果Task.WaitAll成功完成,则断开while循环并使用 Task.Result 提取结果。如果出现异常,请删除出错的任务,然后再次等待其他任务,依此类推。