哪种方法更好:使用Process.Start还是直接调用DLL?

8
在我们的团队中,我们面临着这样的选择:我们需要从我们的C#代码中调用外部第三方代码并处理它的输出。
第三方代码有两种形式:一组dll文件和单个exe文件(可能自己调用这些dll文件)。可能的方法是使用Process.Start语句运行可执行文件并捕获其输出。另一个方法是直接调用dll。
我试图理解我们应该使用哪种方法。
一方面,调用可执行文件很简单,但另一方面,它不太健壮。
一方面,调用dll似乎更正确,但另一方面,为所有我们在本机C代码中拥有的函数提供C#绑定可能是非常复杂的任务。
但我需要更实质性的分析来做出最终决定。是否有人以前遇到过同样的问题,也许你可以分享你的发现。
这将非常有用!
编辑:在这种特殊情况下,我正在谈论视频转换。我需要从用户那里获取视频流并将其转换为一种视频格式。可以调用ffmpeg来完成这项工作,一切都很好,直到出现问题,我需要重新启动编码或采取任何措施。我无法估计需要多长时间,如果我需要同时转换几个视频,ffmpeg将不那么灵活,正如我计划的那样...
至少在我现在看来是这样。当我深入挖掘时,可能会出现更多问题。

1
你需要提供更多的细节... 你尝试过什么?有进行任何测试吗?有任何依赖项(如COM或USB/驱动程序或权限等)吗?有不稳定性吗?你需要哪个级别的控制/细粒度/性能? - Yahia
6个回答

4

有几个注意事项:

  1. 你是否有dll的源代码?
  2. 你打算频繁调用这些dll吗?
  3. dll的API和你的使用情况有多复杂?

根据这些答案,如果:

创建绑定:

  • 你需要经常调用dll。直接调用速度更快。
  • 你已经有了源代码并且检查过它们的好坏。否则,你可能会遇到内存泄漏、调用规范等巨大问题。
  • dll的API不太复杂,因此你不需要向其中发送C++对象等内容,或者在exe中已经实现了很多工作。

使用可执行文件:

  • 如果你只需要偶尔运行它们。创建另一个进程的开销对你来说并不重要。
  • 如果你不确定代码的质量。这会让你的代码更安全、更稳定,而不会加载一些实现不佳的dll。如果出现问题,你总是可以尝试多次运行.exe。但是如果一个dll崩溃了你的应用程序,你将无能为力。
  • 如果API非常复杂,并且exe具有许多功能,那么你将不得不重新实现它们。

只需在此答案中添加,还要考虑可执行文件的启动时间。如果它是一个维护状态等的程序,则在每次调用时支付启动成本可能不是理想的选择。 - Paul Ruane

1

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

  • 如果调用exe,如果它调用多个dll函数,并且其业务流程庞大而复杂-您不希望在C#代码中重新实现所有exe逻辑。
  • 如果exe仅从dll调用一两个函数,则调用顺序和参数已知或根本不存在,则直接调用dll。

通常情况下,我更喜欢直接调用dll,因为这可以消除大量开销和可能的问题,例如生成新进程和处理其输出。如果你的dll函数很简单,不要害怕本地代码,通过PInvoke,您将能够轻松调用这些函数。


0

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并使用marshalling将参数映射到.NET类型


0

我认为这取决于您的代码在库方面需要多少粒度支持。

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

此外,由于您提到这是本地C代码,添加DLL引用意味着必须处理非托管代码,除非没有其他选择,否则我个人不会选择这种方式。


0
如果dll编写良好且没有内存泄漏,最好使用dll,因为它不需要新的进程创建开销。

0

我认为这完全取决于你的需求、时间框架、exe文件输出的稳定性以及它能否轻松解析。两种方法都可行。

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接