如何忽略外部 Dll 的访问冲突异常 - .NET Core 6

发布于 2025-01-13 02:08:45 字数 2864 浏览 1 评论 0原文

我正在使用 DinkToPDF dll 将 XML 转换为 PDF。

我需要生成 2000 个 PDF。

所以我尝试将 PDF 生成逻辑放入 for 循环中。 它生成前 2 或 3 个 PDF,然后在下一次迭代中因本机异常而崩溃,

这是我的 PDF 生成类。在 for 循环中,Generate() 方法将被调用 2000 次

公共静态类 PDFEngine
{
    公共静态无效生成(字符串html,字符串目录,字符串文件名)
    {
        var转换器 = new BasicConverter(new PdfTools());

        转换器.PhaseChanged += Converter_PhaseChanged;
        Converter.ProgressChanged += Converter_ProgressChanged;
        转换器.Finished += Converter_Finished;
        转换器.警告+= Converter_Warning;
        转换器.Error += Converter_Error;

        var doc = new HtmlToPdfDocument()
        {
            全局设置 = {
                颜色模式=颜色模式.颜色,
                方向=方向.肖像,
                纸张尺寸 = PaperKind.A4,
            },
            对象={
                新的对象设置(){
                    页数 = true,
                    Html内容 = html,
                    WebSettings = { DefaultEncoding = "utf-8" },
                    HeaderSettings = { FontSize = 9, Right = "第 [page] 页,共 [toPage]", Line = true },
                    FooterSettings = { FontSize = 9, Right = "第 [page] 页,共 [toPage]" }
                }
            }
        };

        byte[] pdf =转换器.Convert(doc);

        if (!Directory.Exists(目录))
        {
            目录.CreateDirectory(目录);
        }

        使用 (FileStream 流 = new FileStream($"{directory}\\{fileName}", FileMode.Create))
        {
            流.Write(pdf, 0, pdf.Length);
        }
    }

    私有静态无效Converter_Error(对象发送者,DinkToPdf.EventDefinitions.ErrorArgs e)
    {
        Console.WriteLine("[错误] {0}", e.Message);
    }

    私有静态无效Converter_Warning(对象发送者,DinkToPdf.EventDefinitions.WarningArgs e)
    {
        Console.WriteLine("[WARN] {0}", e.Message);
    }

    私有静态无效Converter_Finished(对象发送者,DinkToPdf.EventDefinitions.FinishedArgs e)
    {
        Console.WriteLine("转换{0} ", e.Success ? "成功" : "不成功");
    }

    私有静态无效Converter_ProgressChanged(对象发送者,DinkToPdf.EventDefinitions.ProgressChangedArgs e)
    {
        Console.WriteLine("进度已更改 {0}", e.Description);
    }

    私有静态无效Converter_PhaseChanged(对象发送者,DinkToPdf.EventDefinitions.PhaseChangedArgs e)
    {
        Console.WriteLine("阶段已更改为 {0} - {1}", e.CurrentPhase, e.Description);
    }
}

System.AccessViolationException: '尝试读取或写入受保护的内容 记忆。这通常表明其他内存已损坏。'

输入图片这里的描述

由于这是从非托管 dll 生成的异常,所以我无法捕获它。 输入图片此处描述

我尝试在每个循环中添加

GC.Collect();
GC.WaitForPendingFinalizers();

,但它不起作用。 我完全意识到这个错误是致命的并且不好继续,但我没有办法处理 2000 个文件。

有没有其他方法可以

  1. 抑制异常并继续循环
  2. 通过在不同的应用程序域中运行它来解决此错误?

I'm using DinkToPDF dll to convert an XML to PDF.

I need to generate 2000 PDF's.

So I try to do put the PDF generation logic inside for loop.
It generates first 2 or 3 PDF's and then in the next iteration crashes with a native Exception

This is my PDF generation class. Generate() method will be called 2000 times inside a forloop

public static class PDFEngine
{
    public static void Generate(string html, string directory, string fileName)
    {
        var converter = new BasicConverter(new PdfTools());

        converter.PhaseChanged += Converter_PhaseChanged;
        converter.ProgressChanged += Converter_ProgressChanged;
        converter.Finished += Converter_Finished;
        converter.Warning += Converter_Warning;
        converter.Error += Converter_Error;

        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4,
            },
            Objects = {
                new ObjectSettings() {
                    PagesCount = true,
                    HtmlContent = html,
                    WebSettings = { DefaultEncoding = "utf-8" },
                    HeaderSettings = { FontSize = 9, Right = "Page [page] of [toPage]", Line = true },
                    FooterSettings = { FontSize = 9, Right = "Page [page] of [toPage]" }
                }
            }
        };

        byte[] pdf = converter.Convert(doc);

        if (!Directory.Exists(directory))
        {
            Directory.CreateDirectory(directory);
        }

        using (FileStream stream = new FileStream(
quot;{directory}\\{fileName}", FileMode.Create))
        {
            stream.Write(pdf, 0, pdf.Length);
        }
    }

    private static void Converter_Error(object sender, DinkToPdf.EventDefinitions.ErrorArgs e)
    {
        Console.WriteLine("[ERROR] {0}", e.Message);
    }

    private static void Converter_Warning(object sender, DinkToPdf.EventDefinitions.WarningArgs e)
    {
        Console.WriteLine("[WARN] {0}", e.Message);
    }

    private static void Converter_Finished(object sender, DinkToPdf.EventDefinitions.FinishedArgs e)
    {
        Console.WriteLine("Conversion {0} ", e.Success ? "successful" : "unsucessful");
    }

    private static void Converter_ProgressChanged(object sender, DinkToPdf.EventDefinitions.ProgressChangedArgs e)
    {
        Console.WriteLine("Progress changed {0}", e.Description);
    }

    private static void Converter_PhaseChanged(object sender, DinkToPdf.EventDefinitions.PhaseChangedArgs e)
    {
        Console.WriteLine("Phase changed {0} - {1}", e.CurrentPhase, e.Description);
    }
}

System.AccessViolationException: 'Attempted to read or write protected
memory. This is often an indication that other memory is corrupt.'

enter image description here

Since this is an Exception generating from an Unmanaged dll, I can't catch it.
enter image description here

I tried adding

GC.Collect();
GC.WaitForPendingFinalizers();

during every loop but it's not working.
I'm fully aware that this error is fatal and not good to continue but I don't have a way to process 2000 files.

Is there any other way to either

  1. Suppress the Exception and continue loop
  2. Resolve this error by running it in a different app domain or something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

毁梦 2025-01-20 02:08:45

经过大量的试验和错误,我能够以不同的方式使其工作。

我的意图是跑2000次。
我的问题是,当我将它放入循环中时,我遇到了本机异常

为了使其满足我的需要

  1. 我删除了循环并仅为单个文件生成 PDF。我在命令行参数中收到的这个文件名

  2. 然后我创建了另一个控制台应用程序,它有 2000 次迭代循环,它将调用主应用程序作为 Process.Start(); 我可以通过文件名作为参数

在此处输入图像描述

这样我暂时设法进行任意次数的迭代。由于现在每个进程都有不同的 PID,内存问题不存在

在此处输入图像描述

After a lot of trial and error I was able to make it work with a different way.

My intention is to run in 2000 times.
My issue was when I put it inside the loop, I'm getting native exceptions

To make it work for my need

  1. I removed the loop and generate PDF only for a single file. This file name I receive in a commandline argument

  2. Then I created another console app that got a 2000 iteration loop and it'll call the main app as a Process.Start(); I can pass the filename as arguments

enter image description here

This way I managed to make for any number of iterations for time being. Since each process got different PID now Memory issue is not there

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文