【问题标题】:Which approach better: Process.Start or call DLL directly?哪种方法更好:Process.Start 或直接调用 DLL?
【发布时间】:2013-01-08 03:15:48
【问题描述】:

在我们的团队中,我们面临着选择:我们需要调用外部第三方代码并从我们的 C# 代码处理其输出。

第三方代码有两种形式:一组dlls 和单个exe 文件(可能会单独调用这些dlls)。可能的方法可能是:使用Process.Start 语句运行可执行文件并捕获其输出。还有一种是直接拨打dll

我正在尝试了解我们应该使用哪种方法。

一方面调用可执行文件很简单,但另一方面,它感觉不够健壮。

一方面调用dll 看起来更正确地完成这项工作,但另一方面——为我们在本机C 代码中拥有的所有函数提供C# 绑定可能是一项非常复杂的任务。

但我需要对此主题进行更深入的分析才能做出最终决定。有没有人遇到过同样的问题,也许你可以分享你的发现。

这将非常有用!

编辑:我说的是在这种特殊情况下的视频转换。我需要从用户那里获取视频流并将其转换为一种视频格式。可以调用ffmpeg 来完成这项工作,一切正常,直到出现问题并且我需要重新启动编码或采取任何措施。我无法估计需要多长时间以及是否需要并行转换多个视频ffmpeg 不会像我计划的那样灵活...

至少在我现在看来。当我深入研究时,也许会出现更多问题。

【问题讨论】:

  • 您需要提供更多详细信息...并且:您尝试过什么?你做过什么测试吗?是否有任何依赖项(如 COM 或 USB/驱动程序或权限等)?是否存在不稳定因素?您需要哪种级别的控制/粒度/性能?

标签: c# dll native exe process.start


【解决方案1】:

有几个考虑:

  1. 你有 dll 的来源吗?
  2. 您打算调用这些 dll 多少?
  3. dll 的 API 有多复杂,您的使用情况如何?

取决于答案。

在以下情况下创建绑定:

  • 您会经常调用 dll。直接调用要快得多。
  • 您有来源并检查它们有多好。否则,您可能会遇到内存泄漏、调用约定等方面的巨大问题。
  • dll 的 API 并不太复杂,因此您不需要向它们发送 C++ 对象等。或者实现很多已经在 exe 中完成的工作。

使用可执行文件:

  • 如果您只需要偶尔运行它们。创建另一个流程的开销对您来说并不重要。
  • 如果您不确定代码的质量。对于您的代码来说,它会更加安全和健壮,而不是加载一些实施不良的 dll。如果出现问题,您始终可以尝试多次运行 .exe。但它是一个 dll 使您的应用程序崩溃,您无能为力。
  • 如果 API 非常复杂,并且 exe 有很多功能,那么您将不得不重新实现。

【讨论】:

  • 只需添加到这个答案,还要考虑可执行文件的启动时间。如果它是一个维护状态 &c 的程序。那么每次通话都支付启动费用可能是不可取的。
【解决方案2】:

答案取决于外部应用程序使用它的 dll 的方式。:

  • 调用 exe,如果它多次调用多个 dll 函数,并且它的业务流程又大又复杂 - 你不想在 C# 代码中重新实现所有 exe 逻辑。
  • 直接调用dll,如果exe只从dll中调用一二函数,调用顺序和参数是众所周知的或者根本不存在的。

一般来说,我更喜欢直接调用 dll,因为这消除了很多开销以及产生新进程和处理其输出的可能问题。并且不要害怕原生代码,如果您的 dll 函数很简单,那么使用 PInvoke 您将能够轻松调用这些函数。

【讨论】:

    【解决方案3】:

    EXE 有一个主入口被调用,所以你不能直接调用函数。 调用exe时,会创建一个新进程 在该进程的主线程上下文中调用入口线程。

    DLL 通过直接调用函数为您提供更大的灵活性 每个函数都有一个入口点 系统将 DLL 加载到现有线程的上下文中

    所以调用 DLL 对计算资源来说要好得多,并提供更多的灵活性。考虑到您可以从托管和非托管代码调用 DLL,并且您可以从 C# 调用托管和非托管 dll

    如果DLL有来接口可以直接添加引用,如果没有也可以像下面这样调用它

     [DllImport(@"TestLib.dll")]
        public static extern void InitParam([MarshalAs(UnmanagedType.LPWStr)] string inputFile,
            [MarshalAs(UnmanagedType.LPWStr)] string outputFile,
            [MarshalAs(UnmanagedType.LPWStr)] string templateFile,
            [MarshalAs(UnmanagedType.LPWStr)] string userName,
            [MarshalAs(UnmanagedType.LPWStr)] string manifestFilePath,
            [MarshalAs(UnmanagedType.LPWStr)] string usersRightList);
    

    简单来说,您导入 DLL 并使用编组将参数映射到 .net 类型

    【讨论】:

      【解决方案4】:

      我想说这完全取决于您的要求、时间范围、exe 文件的输出有多稳定,以及解析的难易程度。两种方式都是可行的。

      例如,Mercurial 将其控制台输出视为与其交互的主要方式 - 即使人们可以直接使用其 Python 代码。

      另一方面,从 C# 调用 C 函数相当容易,因此这也是一种选择。但是,如果您需要映射数百个 C 函数,则必须问问自己是否有时间这样做。

      【讨论】:

        【解决方案5】:

        如果 dll 写得很好并且没有内存泄漏,那么最好使用 dll,因为它不需要新的进程创建开销。

        【讨论】:

          【解决方案6】:

          我想说这将取决于您的代码在库的 api 支持方面期望的粒度。

          如果可执行文件对您来说足够好地封装了工作流程,那么您可以从调用可执行文件的简单性中受益。

          另外,由于您提到这是本机 C 代码,添加 DLL 引用将意味着必须处理非托管代码,除非我别无选择,否则我个人不会这样做。

          【讨论】:

            猜你喜欢
            • 2012-02-08
            • 1970-01-01
            • 1970-01-01
            • 2016-05-10
            • 2014-04-28
            • 1970-01-01
            • 2012-06-30
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多