有一个简单的Windows批处理文件可以运行多个应用程序实例:
start app.exe param1
start app.exe param2
有没有办法同时异步运行它们(上面做了)并等待它们完成执行其他操作 - 比如C#
Task.WhenAll(tasksList.ToArray());
/* Process tasksList.Result */
?
/ wait开关在这里没有帮助,如果特定实例仍在运行,可能会进行一些轮询。
答案 0 :(得分:20)
我认为这个问题与Waiting for parallel batch scripts略有不同,因为此应用程序正在等待.exe进程完成而不是批处理脚本。但解决方案几乎相同。
您必须在主批处理脚本中实例化某种形式的轮询。您可以通过重定向有效地创建锁定文件。锁定文件保持锁定状态,直到进程终止。您的批处理脚本轮询,检查它是否可以打开所有锁定文件。一旦成功,就知道所有过程都已结束。
以下解决方案的唯一显着差异是START
直接启动.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
将进程定向到特定的CPU或计算机。该答案还提供了有关锁文件技术如何工作的更全面的解释。
修改强>
可以修改等待循环,以便在添加更多进程时不需要更改:
: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
答案 1 :(得分:1)
根据@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
)。
答案 2 :(得分:0)
基本上,你正在使用START命令正确地执行它,因为它适合你现在需要的东西。
此外,我建议您参考这个好的答案:https://stackoverflow.com/a/1449192/952310
<强>更新强>
要等待每个程序完成,请使用/ W开关,查看:
start /w app.exe param1
start /w app.exe param2
答案 3 :(得分:0)
您正在启动同一app.exe的多个实例?
tasklist |find "app.exe"
,直到%errorlevel%
为1
答案 4 :(得分:0)
Powershell有更复杂的方法可以在没有等待循环的情况下完成它。您可以使用PowerShell包装或调用脚本,甚至可以实现您首选的托管解决方案,就像在C#中一样。
答案 5 :(得分:0)
在单独的批处理文件asynchBatch.bat
中:
start app.exe param1
start app.exe param2
然后在调用者批处理文件中写:
call asynchBatch.bat
other executions
...
只有在app.exe param1和app.exe param2完成后才会启动其他执行。