哪种方法更好:Process.Start 或直接调用 DLL
本文关键字:调用 DLL Start Process 方法 更好 | 更新日期: 2023-09-27 17:55:32
在我们的团队中,我们面临着选择:我们需要调用外部第三方代码并处理其从 C# 代码输出。
第三方代码有两种形式:dll
集和单exe
文件(可能自己调用这些dll
)。可能的方法可能是:使用Process.Start
语句运行可执行文件并捕获其输出。另一个是直接打电话给dll
。
我试图了解我们应该使用哪种方法。
一方面,调用可执行文件很简单,但另一方面,它感觉不健壮。
一方面,调用dll
看起来更正确的工作方式,但另一方面,为本机C
代码中的所有函数提供C#
绑定可能是一项非常复杂的任务。
但我需要对这个话题进行更实质性的分析才能做出最终决定。以前有没有人遇到过同样的问题,也许你可以分享你的发现。
这将是非常有用的!
编辑:我说的是这种特殊情况下的视频转换。我需要从用户那里获取视频流并将其转换为一种视频格式。可以调用ffmpeg
来完成这项工作,一切都很好,直到出现问题,我需要重新启动编码或采取任何操作。我无法估计需要多长时间,如果我需要并行转换多个视频,ffmpeg
不会那么灵活,因为我计划的那样......
至少我现在看到的。也许当我深入研究时会出现更多问题。
有几个注意事项:
- 你有 dll 的来源吗?
- 你打算给这些dll打电话多少?
- dll 的 API 有多复杂,以及您的使用情况?
取决于答案。
在以下情况下创建绑定:
- 您将经常调用 dll。直接呼叫要快得多。
- 你有来源并检查它们有多好。否则,您可能会遇到内存泄漏,调用约定等巨大问题。
- dll 的 API 不太复杂,因此您无需向它们发送C++对象等。或者 imprmenet 在 exe 中已经完成了很多工作。
使用可执行文件:
- 如果您只需要偶尔运行它们。创建另一个进程的开销对您来说无关紧要。
- 如果您不确定代码的质量。对于您的代码来说,这将更加安全和健壮,而不是加载一些实现不佳的 dll。如果出现问题,您始终可以尝试多次运行.exe。但是它 dll 使您的应用程序崩溃,您无法执行任何操作。
- 如果 API 非常复杂,并且 exe 有很多功能,则必须重新实现。
答案取决于外部应用程序使用它的 dll 的方式:
- 调用
- exe,如果它多次调用多个 dll 函数,并且其业务流程庞大而复杂 - 你不希望在 C# 代码中重新实现所有 exe 逻辑。
- 直接调用 dll,如果 exe 只从 dll 调用一两个函数,则调用顺序和参数是众所周知的或根本不存在。
我通常更喜欢直接调用 dll,因为这消除了大量开销和生成新进程和处理其输出时可能出现的问题。不要害怕本机代码,如果你的dll函数很简单,那么使用PInvoke,你将能够轻松调用这些函数。
我想说这取决于你的代码在库的 api 支持方面期望的粒度。
如果可执行文件很好地封装了工作流,则可以从调用可执行文件的简单性中受益。
另外,由于您提到这是本机 C 代码,因此添加 DLL 引用将意味着必须处理非托管代码,除非我没有选择,否则我个人不会选择非托管代码。
如果 dll 写得很好并且没有内存泄漏,则最好使用 dll,因为它不需要新的进程创建开销。
说这完全取决于您的要求,时间范围,exe
文件的输出的稳定性以及解析的难易程度。这两种方式都是可行的。
例如,Mercurial 认为其控制台输出是与其交互的主要方式 - 即使可以直接使用其 Python 代码。
另一方面,从 C# 调用 C 函数相当容易,因此这也是一种选择。但是,如果您需要映射数百个C函数,则必须问问自己是否有时间这样做。
EXE只有一个主条目要调用,因此不能直接调用函数。调用 exe 时,将创建一个新进程入口线程在该进程的主线程的上下文中调用。
.DLL通过直接调用函数为您提供更大的灵活性每个函数都有一个入口点系统将 DLL 加载到现有线程的上下文中
因此,调用 DLL 对于计算资源要好得多,并且提供了更多的可操作性。 考虑到可以从托管和非托管代码调用 DLL,也可以从 C# 调用托管和非托管 DLL
如果DLL有一个come接口,你可以直接添加一个引用,如果没有,你仍然可以像下面这样调用它
[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 类型