繁体   English   中英

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

[英]Which approach better: Process.Start or call DLL directly?

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

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

我试图了解我们应该使用哪种方法。

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

一方面调用dll看起来更正确的方式来完成这项工作,但另一方面 - 为本机C代码中的所有函数提供C#绑定可能真的很复杂。

但我需要对这个主题进行更实质的分析才能做出最终决定。 以前是否有人面对同样的问题,也许你可以分享你的发现。

这将非常有用!

编辑 :我在谈论这个特殊情况下的视频转换。 我需要从用户那里获取视频流并将其转换为一种视频格式。 可以调用ffmpeg来完成这项工作,一切正常,直到出现问题,我需要重新开始编码或采取任何行动。 我无法估计需要多长时间,如果我需要并行转换几个视频, ffmpeg将不会那么灵活,因为我计划它......

至少我现在看到了。 当我深入研究时,可能会出现更多问题。

有几个注意事项:

  1. 你有dll的来源吗?
  2. 你打算打电话给那些dll多少钱?
  3. dll的API和你的用法有多复杂?

取决于答案。

如果创建绑定:

  • 你会经常打电话给dlls。 直接呼叫要快得多。
  • 你有来源并检查它们有多好。 否则,您可能会遇到内存泄漏,调用约定等问题。
  • dll的API不是太复杂,所以你不需要向它们发送C ++对象等。或者在exe中完成很多工作。

使用可执行文件:

  • 如果您只是偶尔需要运行它们。 创建另一个流程的开销对您来说无关紧要。
  • 如果你不确定代码的质量。 它将为您的代码提供更安全和可靠的功能,而不是加载一些执行不当的dll。 如果出现问题,您可以尝试多次运行.exe。 但它是一个dll崩溃你的应用程序,你不能做任何事情。
  • 如果API非常复杂,并且exe具有很多功能,那么您将不得不重新实现。

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

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

此外,既然你提到这是本机C代码,添加DLL引用意味着必须处理非托管代码,除非我没有选择,否则我个人不会这样做。

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

我说这一切都取决于你的要求,时间框架, exe文件输出的稳定性,以及解析它的容易程度。 两种方式都是可行的。

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

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

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类型

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM