简体   繁体   English

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

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

In our team we've faced with the choice: we need to call external third party code and process its output from our C# code. 在我们的团队中,我们面临着这样的选择:我们需要调用外部第三方代码并从C#代码处理其输出。

The third party code available in two forms: set of dll s and single exe file (which is probably calling these dll s on its own). 第三方代码有两种形式:一组dll和单个exe文件(可能是自己调用这些dll )。 And possible approaches could be: use Process.Start statement to run executable and catch its output. 可能的方法可能是:使用Process.Start语句来运行可执行文件并捕获其输出。 And another one is to call dll directly. 另一个是直接调用dll

I'm trying to understand which approach should we use. 我试图了解我们应该使用哪种方法。

On one hand calling executable is simple, but on the other — it does not feel robust. 一方面调用可执行文件很简单,但另一方面 - 它感觉不健壮。

On one hand calling dll looks more right way to do the job, but on the other — it might be really complex task to provide C# binding for all functions we have in native C code. 一方面调用dll看起来更正确的方式来完成这项工作,但另一方面 - 为本机C代码中的所有函数提供C#绑定可能真的很复杂。

But I need more substantial analysis on this topic to make a final decision. 但我需要对这个主题进行更实质的分析才能做出最终决定。 Does anybody faced with the same question before, maybe you could share your finding. 以前是否有人面对同样的问题,也许你可以分享你的发现。

It would be very useful! 这将非常有用!

EDIT : I'm talking about video conversion in this particular case. 编辑 :我在谈论这个特殊情况下的视频转换。 I need to get video stream from user and convert it into one video format for all. 我需要从用户那里获取视频流并将其转换为一种视频格式。 It is possible to call ffmpeg to do the job, and everything is OK until something goes wrong and I need either restart encoding or take any action. 可以调用ffmpeg来完成这项工作,一切正常,直到出现问题,我需要重新开始编码或采取任何行动。 I could not estimate how long it will take and if I will need to convert several videos in parallel ffmpeg will not be that flexible, as I plan it to be... 我无法估计需要多长时间,如果我需要并行转换几个视频, ffmpeg将不会那么灵活,因为我计划它......

At least as I see it now. 至少我现在看到了。 Maybe more issues will come up as I dig in. 当我深入研究时,可能会出现更多问题。

There are several considerations: 有几个注意事项:

  1. Do you have the source for dlls? 你有dll的来源吗?
  2. How much do you intend to call those dlls? 你打算打电话给那些dll多少钱?
  3. How complex are the APIs of dlls, and your usage? dll的API和你的用法有多复杂?

Depending of the answers. 取决于答案。

Create bindings if: 如果创建绑定:

  • You will call dlls frequently. 你会经常打电话给dlls。 Direct call is much faster. 直接呼叫要快得多。
  • You have the source and check how good they are. 你有来源并检查它们有多好。 Otherwise you may have huge problems with memory leaks, calling conventions etc. 否则,您可能会遇到内存泄漏,调用约定等问题。
  • APIs of dlls are not too complex, so you won't need to send C++ objects to them, etc. Or implmenet a lot work already done in exe. dll的API不是太复杂,所以你不需要向它们发送C ++对象等。或者在exe中完成很多工作。

Use executables: 使用可执行文件:

  • If you need to run them only occasionally. 如果您只是偶尔需要运行它们。 Overhead of creating another process does not matter to you. 创建另一个流程的开销对您来说无关紧要。
  • If you not sure about quality of the code. 如果你不确定代码的质量。 It will be much safer and robust for your code, not to load some badly implemented dll. 它将为您的代码提供更安全和可靠的功能,而不是加载一些执行不当的dll。 You can always try to run .exe several times if a problem occurs. 如果出现问题,您可以尝试多次运行.exe。 But it a dll crashes your app, you can't do anything. 但它是一个dll崩溃你的应用程序,你不能做任何事情。
  • If the API is very complex, and exe have a lot of functionality, that you will have to reimplement. 如果API非常复杂,并且exe具有很多功能,那么您将不得不重新实现。

I'd say this would depend on how much granularity would your code expect in terms of api support from the library. 我想这将取决于您的代码在库的api支持方面所期望的粒度。

If executable encapsulates the workflows well enough for you, you could benefit from simplicity of invoking the executable. 如果可执行文件能够很好地封装工作流,那么您可以从调用可执行文件的简单性中受益。

Also, since you mention this is native C code, adding DLL reference would mean having to deal with unmanaged code, which I'd personally not go for unless there is no option for me. 此外,既然你提到这是本机C代码,添加DLL引用意味着必须处理非托管代码,除非我没有选择,否则我个人不会这样做。

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

I'd say it all depends on your requirements, time frame, how stable the output of your exe file is, and how easily it can be parsed. 我说这一切都取决于你的要求,时间框架, exe文件输出的稳定性,以及解析它的容易程度。 Both ways are doable. 两种方式都是可行的。

For example, Mercurial considers its console output the primary way of interacting with it - even though one could use its Python code directly. 例如,Mercurial认为它的控制台输出是与它交互的主要方式 - 即使可以直接使用它的Python代码。

On the other hand, calling C functions from C# is fairly easy so this may be an option as well. 另一方面,从C#调用C函数相当容易,因此这也是一个选项。 If you, however, need to map hundreds of C function, you must ask yourself whether you have the time to do so. 但是,如果您需要映射数百个C函数,则必须问自己是否有时间这样做。

EXE There is single main entry to be called, so you cant call the functions directly. EXE有一个主要的条目被调用,所以你不能直接调用这些函数。 When you call an exe, a new process will be created entry thread is called in context of main thread of that process. 当您调用exe时,将创建一个新进程。在该进程的主线程的上下文中调用入口线程。

DLL Gives you more flexibility by calling functions directly there is an entry point per function system loads a DLL into the context of an existing thread DLL通过直接调用函数为您提供更大的灵活性每个函数系统都有一个入口点将DLL加载到现有线程的上下文中

so calling DLL is much better for computational resources, and provide more flixibility. 所以调用DLL对于计算资源要好得多,并提供更多的灵活性。 talking into consideration that you can call a DLL from managed and unmanaged code, and you can call managed and unmanaged dll from C# 考虑到您可以从托管代码和非托管代码调用DLL,并且可以从C#调用托管和非托管dll

If DLL has a come interface you can add a refrence directly, and if doesnt have you can still able to call it like below 如果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);

in simple words you import the DLL and map the parameters to .net types using marshalling 简单来说,您可以导入DLL并使用编组将参数映射到.net类型

Answer depends on the way external application uses it's dlls.: 答案取决于外部应用程序使用它的方式:

  • Call exe, if it calls multiple dll functions, multiple times and its business process is big and complicated - you don't want to reimplement all exe logic in your C# code. 调用exe,如果它多次调用多个dll函数,并且其业务流程又大又复杂 - 您不希望在C#代码中重新实现所有exe逻辑。
  • Call dll directly, if exe only calls one-two functions from dll, call order and parameters are well known or absent at all. 直接调用dll,如果exe只调用dll中的两个函数,则调用顺序和参数是众所周知的或根本不存在。

I general, I would prefer calling dll directly, because this removed a lot of overhead and possible problems with spawning new process and processing its output. 我一般,我更喜欢直接调用dll,因为这消除了产生新进程和处理其输出的大量开销和可能的问题。 And don't be afraid of native code, if your dll functions are simple then with PInvoke you will be able to easily call those functions. 并且不要害怕本机代码,如果您的dll函数很简单,那么使用PInvoke,您将能够轻松调用这些函数。

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

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