【问题标题】:Using SetCurrentDir and WinExec32AndWait within TParallel.For skips some iterations在 TParallel.For 中使用 SetCurrentDir 和 WinExec32AndWait 会跳过一些迭代
【发布时间】:2016-07-09 06:47:00
【问题描述】:

我对 Tparallel.for 中的迭代次数有疑问。 我有 100 个文件夹,每个文件夹中都有一个要运行的文件(run.bat)。 运行后在文件夹中创建 out.txt 文件。当我使用 Tparalle.for 进行 100 次迭代时,我随机收到 90 到 98 个 out.txt,而它是 100。 我的代码如下(Delphi XE7):

TParallel.For(1, 100, procedure(i: integer)
    begin
      SetCurrentDir(path + '\test\' + IntToStr(i));
      WinExec32AndWait(PChar('run.bat'), 0);
    end);

【问题讨论】:

标签: delphi delphi-xe7


【解决方案1】:

进程工作目录是进程的单个值。您期望每个任务都有自己的私有副本,但这根本不是工作目录的操作方式。在更专业的术语中,共享进程范围的工作目录存在数据竞争。由于创建子进程时的竞争,它们继承了父进程的工作目录,但由于竞争,一些子进程继承了为不同子进程准备的工作目录。这是并行编程所犯的经典错误之一。

通过避免使用父进程工作目录来解决这个问题。根本不要修改它。而是在创建它们时将工作目录传递给每个子进程。这可以使用CreateProcess 或ShellExecuteEx 非常简单地完成。您的 WinExec32AndWait 函数可能需要修改以接受工作目录参数。

这通过确保为每个不同的子进程创建工作目录的单独副本来解决问题。

【讨论】:

  • WinExec32AndWait 函数如下:
  • 函数 WinExec32AndWait(const Cmd: string; const CmdShow: Integer): Cardinal; var StartupInfo: TStartupInfo;流程信息:T流程信息;开始结果 := Cardinal($FFFFFFFF); FillChar(StartupInfo, SizeOf(TStartupInfo), #0);
  • StartupInfo.cb := SizeOf(TStartupInfo); StartupInfo.dwFlags := STARTF_USESHOWWINDOW;//STARTF_USESHOWWINDOW//NORMAL_PRIORITY_CLASS; StartupInfo.wShowWindow := CmdShow;
  • 我实际上对为你编写程序并不是很感兴趣。我在这里尝试做的是解释为什么您的代码会失败以及应该做什么来修复它。我是来帮助人们学习的。如果你想学习,很好。如果你不想学习,只想有人给你代码,那么我就是不适合你的人。
  • @AMIR 如果您有关于您的问题的其他信息,那么您应该编辑问题。不要用 cmets 中的代码淹没我们 - 没有人会一起混淆注释部分
【解决方案2】:

setcurrentdir 当然不是多线程!如果 2 个线程同时将当前目录设置为 xxx 怎么办? :)

改为

Tparallel.for(1,100.procedure(i:integer)
begin
  winexec32andwait(pchar(path+'\test\'+inttostr(i) + '\run.bat'),0);
end);

【讨论】:

  • 可能也需要在子进程中设置工作目录
  • 如果在没有 setcurrentdir 的情况下使用 winexec32andwait,run.bat 文件将不会运行。
  • @AMIR SetCurrentDir 为当前进程设置 global 当前目录。之后,您开始使用批处理。您忘记了多线程方面。 task1 设置当前目录,task2 设置当前目录,task1 启动批处理(哎呀,当前目录错误) - 那是你的问题
  • @AMIR 我在“run.bat”之前添加了一个“\”。往上看。请再试一次。假设你有'\test\1\run.bat'等
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-16
  • 2015-10-31
  • 2022-01-22
  • 2021-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多