試した環境
- Windows 10
本題
以下の処理ではforループ内で指定した回数(ここでは4回)だけサブルーチンを順次に呼び出しています。
サブルーチンは実際の処理の代わりにtimeout
コマンドを呼んでいます。
@echo off pushd %~dp0 for /l %%i in (0, 1, 3) do ( :: call sequentially call :subroutine %%i ) popd pause exit /b :subroutine echo subroutine(%1) timeout /t 10 exit /b
このサブルーチンを並列に呼び出したいと思ったとき、start
コマンドを使った以下の方法では上手くいきません。
@echo off pushd %~dp0 for /l %%i in (0, 1, 3) do ( :: call parallelly? start call :subroutine %%i ) popd pause exit /b :subroutine echo subroutine(%1) timeout /t 10 exit /b
上記処理を実行すると、立ち上がったそれぞれのコマンドプロンプトで以下の文章が表示されます。
バッチ スクリプト外でバッチ ラベルを呼び出すことはできません。
そこで強引な方法ですが、自分自身のバッチを呼び出すことでサブルーチンを並列に呼び出します。 以下にスクリプト例を示します。
@echo off if "%1"=="" ( pushd %~dp0 for /l %%i in (0, 1, 3) do ( :: call parallelly start call "%0" call_myself %%i ) popd pause ) else if "%1"=="call_myself" ( call :subroutine %2 ) exit /b :subroutine echo subroutine(%1) timeout /t 10 exit /b
実装する際には、呼び出し先が再びstart
コマンドを呼び出すような無限ループにならないように十分気を付けてください。
私は一度やってしまいました。
並列に立ち上げたコマンドプロンプトを処理終了後に閉じたい場合は、
上記スクリプトでstart call "%0" call_myself %%i
の行をstart cmd /c "%0" call_myself %%i
に書き換えると実現できます。
このことは以下の記事に書きました。