There is a simple Windows batch file that runs multiple instances of application:
start app.exe param1
start app.exe param2
Is there a way to run them asynchronously at the same time (which above does) and wait for them both to finish to perform other actions - something like C#
Task.WhenAll(tasksList.ToArray());
/* Process tasksList.Result */
?
/wait switch will not help here, some polling for if particular instance is still running maybe.
I suppose this question is slightly different than Waiting for parallel batch scripts in that this application is waiting for .exe processes to finish instead of batch scripts. But the solution is nearly identical.
You must instantiate some form of polling in your master batch script. You can effectively create a lock file via redirection. The lock file remains locked until the process terminates. Your batch script polls, checking if it can open all the lock files. Once it succeeds, it knows all the processes have ended.
The only significant difference in the solution below is that START
launches the .exe directly instead of launching a batch through CMD /C
. I also learned that (call )
is an extremely fast way to effectively perform a no-op that always succeeds. So I substitued (call )
in place of 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
See Parallel execution of shell processes for a pretty sophisticated application of the lock technique that regulates the maximum number of parallel processes, with the ability to direct processes to specific CPUs or machines via PSEXEC
. That answer also provides a fuller explanation of exactly how the lock file technique works.
EDIT
The wait loop can be modified so that it does not need to change as you add more processes:
: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