CreateProcess 的快速替代方案

Posted

技术标签:

【中文标题】CreateProcess 的快速替代方案【英文标题】:Fast alternative to CreateProcess 【发布时间】:2012-09-27 13:23:07 【问题描述】:

我正在寻找一种快速替代 Delphi 中的 CreateProcess 的方法,以在 exe 中执行某些计算,包括 XML 中的几个返回值。 目前,我正在调用带有某些参数的 C#-exe。其中一个电话大约需要。 0.5 秒 - 这方式太昂贵了,因为这个 exe 需要调用几百次(不幸的是迭代调用,即多线程不会加快工作速度)。

我当前的代码如下所示(在 *** 上找到了获取 exe somwhere 的控制台输出的解决方案)。

IsExecutable := CreateProcess(
            nil,
            PChar(WorkDir + Exe + CommandLine),
            nil,
            nil,
            True,
            HIGH_PRIORITY_CLASS,
            nil,
            nil,
            StartupInfo,
            ProcessInformation);
CloseHandle(StdOutPipeWrite);
    if IsExecutable then
      try
        repeat
          WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
          if BytesRead > 0 then
          begin
            Buffer[BytesRead] := #0;
            Result := Result + Buffer;
          end;
        until not WasOK or (BytesRead = 0);
        WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
      finally
        CloseHandle(ProcessInformation.hThread);
        CloseHandle(ProcessInformation.hProcess);
      end

顺便说一句,我不是很好的 Delphi - 实际上,我有点像“我不知道自己在做什么”狗模因...

【问题讨论】:

【参考方案1】:

创建新流程的成本很高。除了使用CreateProcess,别无选择。这里没有快速修复。没有什么神奇的按钮可以让进程创建超级快。

解决您的问题的方法是完全停止创建新流程。在您的流程中执行此任务。

【讨论】:

或者如果由于某种原因必须保持进程分离,则启动一次并继续与它通信,这样您就不必重复重新创建它(仍然会有开销,但意义不大)。 @Thomas 是的。 IPC 可能很昂贵,但进程内可能是唯一的答案。如果计算足够重要,那么 IPC 成本可以忽略不计。如果计算成本低,那么 IPC 可能占主导地位。【参考方案2】:

您是否需要每次都创建一个新流程?或者你可以重复使用同一个实例吗? 您可以使用一些低级控制台输入/输出管道(您的代码看起来像您现在正在尝试这样做:)),或者您可以使用某种 IPC(互斥+共享内存,在 2 个进程之间复制数据),或者您可以通过 TCP/IP 通信来使用更多的 n 层(或客户端/服务器)方法(RemObjects SDK 非常适合这一点,具有 .Net 和 Delphi 库,它们通过 TCP/IP 进行通信,或者Windows 消息、命名管道等)。然而,由于抽象,最后一种方法增加了一些延迟/开销,但比在 .Net 和 Delphi 中自己实现双方更容易使用(顺便说一句,这并不难)。

【讨论】:

说到IPC,查看www.cromis.net/blog/downloads/cromis-ipc/【参考方案3】:

如David wrote 和André wrote,您无法更改此设置。

这是真正的big differences between Windows and Linux 之一。 Windows 中的 CreateProcess 非常昂贵,而 Linux 中的 fork 很便宜。另一方面,Linux fork 通常后面跟着一个 exec,这很昂贵。这就是为什么.NET introduced the AppDomain which is faster。

您可以通过几个方向将 .NET 代码集成到您的流程中,例如 Arnaud wrote。

您可以做的另一件事是在 Delphi 进程和 .NET 进程之间进行 IPC(例如使用命名管道),并让 .NET 进程对每个请求使用 AppDomain。

【讨论】:

没有 exec 的 fork 没有多大用处 其实它的很多服务器。 这不是这里发生的事情 那么不要对试图提供一些背景信息的答案做出绝对陈述,以说明事情为何如此。 AppDomain 位于 fork 和 CreateProcess 的中间。因此,对我答案的最后一行的介绍。【参考方案4】:

这里比较慢的是创建一个新进程,而且每次运行可执行文件时都会启动整个 .Net 框架进程。

为了获得最佳性能,您最好将 C# 进程公开为 COM,然后直接从 Delphi 调用它。

我猜,在这种情况下,通过 TCP/IP 进行远程连接是不值得的。几年前,我在本地机器上使用 RemObjects 的速度实验很糟糕。

你需要的是调用 COM 互操作,你可能会感兴趣:

Exposing .Net components to COM; Managed VCL; Hydra。

Delphi 很好地处理 COM 对象,您可以很容易地从 Delphi 代码中调用 C# 方法。

【讨论】:

【参考方案5】:

改用线程池还是 IOCP?是的,它有点复杂和消耗资源,但消除了执行外部进程的需要。新的 ThreadPool API(Vista 及更高版本)为您提供更多机会和灵活性(您甚至可以标记长时间运行的任务):

Thread Pools Overview TP APIs SetThreadpoolCallbackRunsLong

【讨论】:

以上是关于CreateProcess 的快速替代方案的主要内容,如果未能解决你的问题,请参考以下文章

process_begin: CreateProcess(NULL,......) make (e=87): 参数错误。

bonecp 连接池的快速可靠替代方案

对于尺度不变的特征提取,SURF 和 SIFT 是不是有任何快速的替代方案?

是否存在“SendKeys”的快速且可预测的替代方案?

HSQLDB 文件模式的快速切换替代方案(我现在需要并发访问)

如何获得CreateProcess启动的进程返回的结果