你知道有没有简单的方法可以运行为了在多线程批处理文件中执行命令?如果我无法在 4 个并行线程中运行任务,那么拥有 4 个核心有什么意义?
例如,如果我使用 PNGOUT 优化 PNG,我将使用的命令是
for %i in (*.png) do pngout "%i"
但这是一个高度可并行的任务,其中的子任务根本不相互依赖。
要在 4 个“队列”中运行这个,我会写类似的东西
for -thread 4 %i in (*.png) do pngout "%i"
我是否需要编写自己的类似应用程序来实现这一点,或者是否有可用的免费解决方案?
答案1
不久前,我在 Stack Overflow 上编写了一个仅执行最大数量命令的批处理文件:shell 进程的并行执行:
@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
它最多生成四个并行执行且最小化的新进程。等待时间可能需要调整,具体取决于每个进程执行多少以及运行多长时间。如果您正在执行其他操作,您可能还需要调整 tasklist 正在查找的进程名称。
但是,没有办法正确计算此批处理产生的进程数。一种方法是在批处理开始时创建一个随机数 (
%RANDOM%
),并创建一个辅助批处理来执行处理(或产生处理程序),但可以将其窗口标题设置为参数:@echo off title %1 "%2" "%3"
这将是一个简单的批处理,将其标题设置为第一个参数,然后以第三个参数运行第二个参数。然后,您可以通过仅选择具有指定窗口标题 (
tasklist /fi "windowtitle eq ..."
) 的进程来过滤任务列表。这应该相当可靠,并可防止出现太多误报。cmd.exe
如果您仍有一些实例在运行,那么搜索将是一个坏主意,因为这会限制您的工作进程池。您可以使用它
%NUMBER_OF_PROCESSORS%
来创建生成多少个实例的合理默认值。您还可以轻松地将其用于
psexec
远程生成进程(但不太可行,因为您必须拥有另一台机器的管理员权限,并在批处理中提供密码)。不过,您必须使用进程名称进行过滤。
答案2
批处理文件用于编写极其基本的脚本,不支持任何类型的多线程。您需要编写自己的实用程序来完成您想要完成的任务。
或者,Windows PowerShell可能会提供更多功能,让您更接近目标。
如果你只是想同时运行多个操作,你可以使用命令开始在新窗口中打开 PNGOUT 实用程序。然后 FOR 循环将继续,而无需等待每个操作完成。
修改后的行将如下所示:
for %i in (*.png) do start pngout "%i"
但请注意,这将有效启动 PNGOUT全部目录中的文件,这很可能是不可取的。
答案3
我编写了一个库,它在批处理文件中提供多线程支持(以“模拟”线程池行为的方式)