多线程 Windows FOR 批处理命令

Axa*_*dax 12 automation batch

您知道是否有一种简单的方法可以在多个线程的批处理文件中运行FOR命令吗?如果我不能在 4 个并行线程中运行我的任务,那么拥有 4 个内核有什么意义?

例如,如果我使用 PNGOUT 优化 PNG,我将使用的命令是

for %i in (*.png) do pngout "%i"
Run Code Online (Sandbox Code Playgroud)

但这是高度可并行化的任务,其中子任务根本不相互依赖。

要在 4 个“队列”中运行它,我会写一些类似的东西

for -thread 4 %i in (*.png) do pngout "%i"
Run Code Online (Sandbox Code Playgroud)

我是否需要编写自己的类似 for 的应用程序来执行此操作,或者是否有可用的免费解决方案?

Joe*_*oey 13

不久前,我在 Stack Overflow: Parallel execution of shell processes上编写了一个批处理文件,该文件只执行最大数量的命令:

@echo off
for /l %%i in (1,1,20) do call :loop %%i
goto :eof

:loop
call :checkinstances
if %INSTANCES% LSS 5 (
    rem just a dummy program that waits instead of doing useful stuff
    rem but suffices for now
    echo Starting processing instance for %1
    start /min wait.exe 5 sec
    goto :eof
)
rem wait a second, can be adjusted with -w (-n 2 because the first ping returns immediately;
rem otherwise just use an address that's unused and -n 1)
echo Waiting for instances to close ...
ping -n 2 ::1 >nul 2>&1
rem jump back to see whether we can spawn a new process now
goto loop
goto :eof

:checkinstances
rem this could probably be done better. But INSTANCES should contain the number of running instances afterwards.
for /f "usebackq" %%t in (`tasklist /fo csv /fi "imagename eq wait.exe"^|find /v /c ""`) do set INSTANCES=%%t
goto :eof
Run Code Online (Sandbox Code Playgroud)

它最多产生四个并行执行并最小化的新进程。等待时间可能需要调整,这取决于每个进程做了多少以及运行了多长时间。如果您正在做其他事情,您可能还需要调整任务列表正在查找的进程名称。

但是,无法正确计算此批处理产生的进程。一种方法是在批处理开始时创建一个随机数 ( %RANDOM%) 并创建一个辅助批处理来执行处理(或生成处理程序),但可以将其窗口标题设置为参数:

@echo off
title %1
"%2" "%3"
Run Code Online (Sandbox Code Playgroud)

这将是一个简单的批处理,将其标题设置为第一个参数,然后使用第三个参数运行第二个参数。然后,您可以通过仅选择具有指定窗口标题 ( tasklist /fi "windowtitle eq ...") 的进程在任务列表中进行过滤。这应该工作相当可靠,并防止过多的误报。cmd.exe如果您仍有一些实例在运行,搜索将是一个坏主意,因为这会限制您的工作进程池。

您可以使用它%NUMBER_OF_PROCESSORS%来创建一个合理的默认值来生成多少个实例。

您还可以轻松地调整它以用于psexec远程生成进程(但不太可行,因为您必须在另一台机器上拥有管理员权限并在批处理中提供密码)。但是,您必须使用进程名称进行过滤。