2

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

我当前的代码看起来像这样(在 StackOverflow 上找到了获取 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

顺便说一句,我不是很好的德尔福 - 实际上,我有点像“我不知道我在做什么”狗模因的东西......

4

5 回答 5

8

创建新流程的成本很高。没有其他方法可以使用CreateProcess. 这里没有快速修复。没有神奇的按钮可以让流程创建变得超级快。

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

于 2012-09-27T13:29:11.177 回答
3

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

于 2012-09-27T13:57:46.970 回答
3

就像大卫写的和安德烈写的一样,你无法改变这一点。

这是Windows 和 Linux 之间真正的巨大差异之一。CreateProcess在 Windows 中非常昂贵,而fork在 Linux 中则很便宜。另一方面,Linuxfork通常紧随其后的exec是昂贵的。这就是.NET 引入AppDomainwhich is faster的原因。

有几个方向可以将 .NET 代码集成到您的流程中,就像Arnaud 所写的那样。

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

于 2012-09-27T17:04:59.367 回答
1

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

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

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

您需要的是调用 COM 互操作,您可能对以下内容感兴趣:

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

于 2012-09-27T15:43:26.513 回答
0

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

于 2012-09-27T20:45:00.253 回答