1

主要背景

我们实际上是在尝试获取 Ghostscript x64 DLL 的多线程版本,以便通过 Ghostscript .NET 使用它。该组件应该“允许在单个进程中同时运行多个 Ghostscript 实例”,但是,正如我们在项目中检查的那样,在向应用程序发出并发请求之前工作正常。可以使用相同的方法复制相同的行为Tasks。在这两种情况下引发的错误描述是:

调用“gsapi_new_instance”时发生错误:-100

即使它似乎与 .NET 没有直接关系,我也会发布我们的 C# 方法代码示例,仅用于上下文化。

// Define switches...
string[] switchesArray = switches.ToArray();

using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
    try
    {
        procesador.StartProcessing(switchesArray, null);

        byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);

        return destinationFile;

    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        System.IO.File.Delete(sourceFile);
    }
}

线程安全解决方案

开始我们的调查,我们在这篇文章中找到了这个 KenS 的答案,表明 Ghostscript DLL 必须使用 GS_THREADSAFE 编译器定义生成。

澄清一下,当我们使用 Ghostscript 9.52 x64 来生成 PDF 时,我们需要为发布配置编译这个 x64 DLL。在尝试在 Windows 10 x64 机器上编译 Ghostscript 源代码后,使用 Visual Studio Community 2017 和 Visual Studio Community 2019,我们终于设法在没有 GS_THREADSAFE 参数的情况下构建和生成所有项目(仅限 VS Community 2019),只是为了确认编译正常,我们检查 DLL 和可执行文件是否正常工作。对于这个过程,我们记住了我们在Ghostscript 官方文档中找到的所有内容。

由于我们没有其他指南来包含此 GS_THREADSAFE 参数,因此我们按照此解决方案中给出的说明进行操作,包括XCFLAGS="-DGS_THREADSAFE=1"在 nmake 构建命令上,将这句话用于Rebuild all选项:

cd .. && nmake -f psi\msvc32.mak WIN64= SBR=1 DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 && nmake -f psi\msvc32.mak WIN64= DEVSTUDIO= XCFLAGS=-DGS_THREADSAFE=1 bsc

这种方法在构建过程中会出现错误:

函数 gs_log_error 文件 \mkromfs.obj 1 中引用的错误 LNK2019 未解析的外部符号 errprintf_nomem

看起来,文件mkromfs.c有一个名为errprintf_nomem的方法,在设置 GS_THREADSAFE 时找不到该方法。

问题

1 - 是否有任何包含编译为 THREADSAFE 的 x64 DLL 的 Ghostscript 公开版本?

而且,如果不是(这就是我的猜测......)

2 - 是否可以在不更改源代码的情况下将此 DLL 设为 THREADSAFE?

3-请任何人提供分步指南或演练,以使用 GS_THREADSAFE 在 Windows 10 x64 上使用 Visual Studio(甚至任何其他可能的替代方案)构建 x64 Ghostscript DLL?

4 - 一些帖子谈到人们使用 Ghostscript .NET 来管理多线程。我假设这些示例都使用 GS_THREADSAFE DLL ...我们是否通过了任何其他解决方法?

提前非常感谢。

4

2 回答 2

1

总结所有这些问题,并作为未来开发人员遇到同样问题的指南,这些是我们迄今为止找到的答案:

  1. 正如@KenS 在他的回复中提到的那样:“不,Ghostscript 开发人员实际上并没有构建二进制文件的线程安全版本。”

  2. 此时此刻,显然不是,因为已经报告了这个打开的错误

  3. 由于这似乎是商业许可支持的问题,我们不再对这一点发表评论。

  4. 再次感谢@HABJAN。我绝对收回我在问题上所说的话,因为可以让 Ghostscript .NET 在多线程场景中工作。下面是我们应用的解决方案,以防它对某人有用。

基于 HABJAN 示例,我们为实现这一目标所做的是创建一个自定义类来捕获 Ghostscript 日志记录:

protected class ConsoleStdIO : Ghostscript.NET.GhostscriptStdIO
{
    public ConsoleStdIO(bool handleStdIn, bool handleStdOut, bool handleStdErr) : base(handleStdIn, handleStdOut, handleStdErr)
    {
    }

    public override void StdIn(out string input, int count)
    {
        char[] userInput = new char[count];
        Console.In.ReadBlock(userInput, 0, count);
        input = new string(userInput);
    }

    public override void StdOut(string output)
    {
        //log
    }

    public override void StdError(string error)
    {
        //log
    }
}

对于我们之前的方法,我们简单地包含对此类的调用,这样可以避免同时执行多个任务时出现错误:

// Define switches...
string[] switchesArray = switches.ToArray();

using (GhostscriptProcessor procesador = new GhostscriptProcessor())
{
    try
    {
        procesador.StartProcessing(switchesArray, new ConsoleStdIO(true, true, true));

        byte[] destinationFile = System.IO.File.ReadAllBytes(destinationPath);

        return destinationFile;

    }
    catch (Exception ex)
    {
        throw ex;
    }
    finally
    {
        System.IO.File.Delete(sourceFile);
    }
}
于 2020-09-25T07:42:58.653 回答
-1

好吧,在我看来,您在这里寻求技术支持。

您显然想在商业活动中使用 Ghostscript,实际上有人可能会合理地说您想要一个企业版的 Ghostscript。大概您不想更改源代码以允许您使用开源许可证,因为您不想为商业许可证付费。

考虑到这一点,您的问题的答案是:

  1. 不,Ghostscript 开发人员实际上并没有构建二进制文件的线程安全版本。
  2. 目前,没有。这可能是一个疏忽。
  3. 那将是一个技术支持问题,不能保证免费用户得到技术支持,这是双许可证供应商说服人们使用商业许可证的少数几个杠杆领域之一。所以我希望你能理解我不会提供那个。
  4. 据我所知,没有。
于 2020-09-15T15:17:19.110 回答