c#异常后继续

Continue after an exception in c#

我正在尝试获取大约的文档类型。 3k链接。但是当它触及 700-900 标记线时,我总是得到一个例外。

如何在异常发生的地方继续(所以我没有义务再次从零开始)?这可能吗?

这是我使用的代码:

     try
        {
            Parallel.ForEach(linkList, link => 
            {
                stopwatch.Restart();
                Console.Write($"Downloading page {index++} of {linkList.Count}...");
                documents.Add(LoadPage(link));
                Console.Write($" in {stopwatch.Elapsed.TotalMilliseconds} ms");
                Console.WriteLine();
            });

            return documents;
        }
        catch (Exception e)
        {
            ???
        }

尝试将内部代码包装在 try-catch 中

        Parallel.ForEach(linkList, link => 
        {
            try
            {
                stopwatch.Restart();
                Console.Write($"Downloading page {index++} of {linkList.Count}...");
                documents.Add(LoadPage(link));
                Console.Write($" in {stopwatch.Elapsed.TotalMilliseconds} ms");
                Console.WriteLine();
            }
            catch (Exception e)
            {
                ???
            }
        });

        return documents;

编辑:

您可能还想查看 thread-safe collections C# 必须提供的内容,因为普通集合不是线程安全的

您只需要在 ForEach

中处理它们
Parallel.ForEach(linkList, link => 
{
    try
    {
       ...
     }
     catch(Exception ex)
     {
        // log
     }
});

然而你的问题远不止于此。

  1. 这看起来像是 IO 绑定工作负载,不适合 Parallel.ForEach
  2. documents.Add 看起来不是线程安全的
  3. 你的索引会出来

老实说,这看起来确实像是 TPL Dataflow 的工作,它让您受益于 async 和 await和 IO 绑定工作负载。使用 async 和 await,将停止扰动任务计划程序,让 IO 完成端口完成它们的工作,释放线程池。

它还允许您制作更复杂的管道,并且能够在需要时自行将失败的作业重新送回,还有许多其他优势

好的,这就是让我实现目标的解决方案。

        var index = 1;
        Parallel.ForEach(linkList,  link => { GetDocuments(stopwatch, index++, linkList, documents, link); });

        if (FailedDownloads.Count > 0)
        {
            linkList = new List<string>(FailedDownloads);
            FailedDownloads.Clear();
            Parallel.ForEach(linkList,
                link => { GetDocuments(stopwatch, index++, linkList, documents, link); });
        }
        return documents;
    }

    private void GetDocuments(Stopwatch stopwatch, int index, List<string> linkList, List<HtmlDocument> documents, string link)
    {
        stopwatch.Restart();
        Console.Write($"Downloading page {index} of {linkList.Count}...");
        try
        {
            documents.Add(LoadPage(link));
            Console.Write($" in {stopwatch.Elapsed.TotalMilliseconds} ms");
        }
        catch (AggregateException e)
        {
            if (e.InnerExceptions[0] is HttpRequestException)
            {
                FailedDownloads.Add(link);
                Console.WriteLine(e);
            }
            else
            {
                throw;
            }
        }