有一个运行多个应用程序实例的简单 Windows 批处理文件:
start app.exe param1
start app.exe param2
有没有办法同时异步运行它们(上面确实如此)并等待它们都完成以执行其他操作 - 比如 C#
Task.WhenAll(tasksList.ToArray());
/* Process tasksList.Result */
?
/wait 开关在这里没有帮助,如果特定实例仍在运行,可能会进行一些轮询。
有一个运行多个应用程序实例的简单 Windows 批处理文件:
start app.exe param1
start app.exe param2
有没有办法同时异步运行它们(上面确实如此)并等待它们都完成以执行其他操作 - 比如 C#
Task.WhenAll(tasksList.ToArray());
/* Process tasksList.Result */
?
/wait 开关在这里没有帮助,如果特定实例仍在运行,可能会进行一些轮询。
我想这个问题与等待并行批处理脚本略有不同,因为此应用程序正在等待 .exe 进程完成而不是批处理脚本。但解决方案几乎相同。
您必须在您的主批处理脚本中实例化某种形式的轮询。您可以通过重定向有效地创建锁定文件。锁定文件保持锁定状态,直到进程终止。您的批处理脚本会轮询,检查它是否可以打开所有锁定文件。一旦成功,它就知道所有进程都已结束。
以下解决方案的唯一显着区别是START
直接启动 .exe 而不是通过 .exe 启动批处理CMD /C
。我还了解到,这(call )
是一种非常快速的方法,可以有效地执行始终成功的无操作。所以我代替(call )
了rem
@echo off
setlocal
set "lock=%temp%\wait%random%.lock"
:: Launch processes asynchronously, with stream 9 redirected to a lock file.
:: The lock file will remain locked until the script ends.
start "" 9>"%lock%1" notepad.exe
start "" 9>"%lock%2" notepad.exe
:Wait for both processes to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%N in (1 2) do (
(call ) 9>"%lock%%%N" || goto :Wait
) 2>nul
::delete the lock files
del "%lock%*"
:: Finish up
echo Done - ready to continue processing
请参阅Parallel execution of shell processes了解锁技术的一个非常复杂的应用程序,该技术调节并行进程的最大数量,并能够通过PSEXEC
. 该答案还对锁定文件技术的工作原理提供了更全面的解释。
编辑
可以修改等待循环,以便在添加更多进程时不需要更改:
:Wait for all processes to finish (wait until lock files are no longer locked)
1>nul 2>nul ping /n 2 ::1
for %%F in ("%lock%*") do (
(call ) 9>"%%F" || goto :Wait
) 2>nul
适应@dbenham的答案,这就是我如何让它在一个for
和无限数量的进程中工作:
setlocal enabledelayedexpansion
for %%a in (*.*) do start "" 9>"%temp%/wait!random!.lock" /b /low "myprogram.exe" -program_parameters
:wait
ping /n 2 ::1 > nul
echo waiting processes to finish...
2>nul del "%temp%\wait*.lock" > nul
if exist "%temp%\wait*.lock" goto :wait
... more commands ...
这里%random%
不起作用,因为它在for
被调用时被扩展,因此使所有数字都相同。所以我enabledelayedexpansion
和使用!random!
.
在循环中,我尝试删除所有文件。2>nul
将确保任何错误都不会显示在屏幕上。只有在可以删除所有内容时才会通过(if exist
)。
您正在启动同一个 app.exe 的多个实例?
tasklist |find "app.exe"
直到%errorlevel%
是1
Powershell 有更复杂的方法来做到这一点,而无需等待循环。您可以使用 powershell 包装或调用您的脚本,甚至可以实现您首选的托管解决方案,以便完全按照您在 C# 中执行的操作。
在单独的批处理文件asynchBatch.bat
中放置:
start app.exe param1
start app.exe param2
然后在调用者批处理文件中写入:
call asynchBatch.bat
other executions
...
只有在 app.exe param1 和 app.exe param2 都完成后,才会开始其他执行。
基本上,您使用START命令是正确的,因为它是为您现在需要的而设计的。
此外,我建议您参考这个很好的答案:https ://stackoverflow.com/a/1449192/952310
更新:
要等待每个程序完成,请使用 /W 开关,查看:
start /w app.exe param1
start /w app.exe param2