Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 通过start命令返回变量_Windows_Multithreading_Batch File_Scope - Fatal编程技术网

Windows 通过start命令返回变量

Windows 通过start命令返回变量,windows,multithreading,batch-file,scope,Windows,Multithreading,Batch File,Scope,我正在寻找一种从启动命令启动的批处理脚本中获取返回值的方法。让我解释一下: 我需要通过从主批处理脚本同时启动多个子批处理脚本来利用多处理,然后在完成时检索每个子批处理文件返回值 我在call命令中使用了return变量,这一点在下面得到了很好的解释。 该解决方案不允许多线程,因为子批处理脚本是一个接一个地运行的 使用start命令允许多个正在运行的批处理脚本,但不会将值返回到主脚本,因为start命令显然创建了一个全新的变量上下文 是否有人有从子脚本返回值到主脚本的解决方案/解决方法 以下是我需

我正在寻找一种从启动命令启动的批处理脚本中获取返回值的方法。让我解释一下:

我需要通过从主批处理脚本同时启动多个子批处理脚本来利用多处理,然后在完成时检索每个子批处理文件返回值

我在call命令中使用了return变量,这一点在下面得到了很好的解释。 该解决方案不允许多线程,因为子批处理脚本是一个接一个地运行的

使用start命令允许多个正在运行的批处理脚本,但不会将值返回到主脚本,因为start命令显然创建了一个全新的变量上下文

是否有人有从子脚本返回值到主脚本的解决方案/解决方法

以下是我需要的模型:

mainScript.bat

@echo off
setlocal

set "retval1=0"
set "retval2=0"
REM run two scripts in parallel:
start "" subscript1.bat arg1 retval1
start "" subscript2.bat arg1 retval2

REM wait for returned value
:waiting
call :sleep 1
set /a "DONE=1"
if %retval1% equ 0 set "DONE=0"
if %retval2% equ 0 set "DONE=0"
if %DONE% equ 0 goto :waiting

echo returned values are %retval1% %retval2%
exit /b
@echo off
setlocal
set "arg1=%~1"
set "retval1=%~1"

REM do some stuff...

REM return value
(endlocal
  set "%retval1%=%foo%"
)
exit /b
订阅1.bat

@echo off
setlocal

set "retval1=0"
set "retval2=0"
REM run two scripts in parallel:
start "" subscript1.bat arg1 retval1
start "" subscript2.bat arg1 retval2

REM wait for returned value
:waiting
call :sleep 1
set /a "DONE=1"
if %retval1% equ 0 set "DONE=0"
if %retval2% equ 0 set "DONE=0"
if %DONE% equ 0 goto :waiting

echo returned values are %retval1% %retval2%
exit /b
@echo off
setlocal
set "arg1=%~1"
set "retval1=%~1"

REM do some stuff...

REM return value
(endlocal
  set "%retval1%=%foo%"
)
exit /b

除了将返回值写入文件之外,找不到任何替代方法,因此

main

@ECHO关闭
SETLOCAL
对于(12)个do中的%%a(
删除“%temp%\retval%%a”2>num
)
开始/分钟“q225220791.bat arg1 retval1
选项/t 1/d y>nul
开始/分钟“q225220791.bat arg1 retval2
:等待
选项/t 1/d y>nul
回显等待…%retval1%…%retval2%
如果不存在“%temp%\retval1”,则转到等待
如果不存在“%temp%\retval2”,则转到等待
对于(12)个do中的%%a(
对于/f“usebackqdelims=“%%i in”(“%temp%\retval%%a”)设置“retval%%a=%%i”
)
对于(12)个do中的%%a(
删除“%temp%\retval%%a”2>num
)
回显返回值为%retval1%%retval2%
后藤:EOF
q225220791.bat

@echo off
setlocal

set "retval1=0"
set "retval2=0"
REM run two scripts in parallel:
start "" subscript1.bat arg1 retval1
start "" subscript2.bat arg1 retval2

REM wait for returned value
:waiting
call :sleep 1
set /a "DONE=1"
if %retval1% equ 0 set "DONE=0"
if %retval2% equ 0 set "DONE=0"
if %DONE% equ 0 goto :waiting

echo returned values are %retval1% %retval2%
exit /b
@echo off
setlocal
set "arg1=%~1"
set "retval1=%~1"

REM do some stuff...

REM return value
(endlocal
  set "%retval1%=%foo%"
)
exit /b
@ECHO关闭
SETLOCAL
::随机等待2..10秒。
设置/a超时=%RANDOM%%%8+2
选项/t%超时%/d y>nul
::返回随机结果12..20
SET/a foo=%RANDOM%%%8+12
>%temp%\%2“回显%foo%
端部
出口

依赖子进程的第二个参数的值来设置临时文件名。我已经更改了批的名称以适应我的系统。

不确定这是否可行,但只是测试以避免临时文件。所以为了在子进程中寻找一个可以从父进程读取的位置,我决定使用窗口标题

task.cmd

@echo off
    setlocal

rem Retrieve task information and set window title    
    set "taskID=%~1"
    title [task];%taskID%;working;

rem Retrieve the rest of parameters. For this sample, a random value
    set /a "timeToWait=%~2 %% 30"

rem Simulate command processing
    timeout /t %timeToWait%

rem Calculate a return value for this task
    for /f "tokens=1-10 delims=,.:/ " %%a in ("%date%%time%_%~2") do set "returnValue=%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j"

rem Signal the end of the task
    title [task];%taskID%;ended; my return value is %returnValue% ;

rem Wait for master to end this tasks
    cls
    echo Waiting for master....
    waitfor %taskID%

rem Cleanup    
    endlocal
@echo off

    setlocal enableextensions enabledelayedexpansion

rem Configure tasks
    set "taskPrefix=myTSK"
    set "numTasks=5"

rem Start tasks
    for /l %%a in (1 1 %numTasks%) do (
        set "return[%taskPrefix%%%a]=unknown"
        start "[task];%taskPrefix%%%a;working;" cmd /c "task.cmd %taskPrefix%%%a !random!"
    )

rem Wait for tasks to start    
    timeout /t 2 > nul

rem Wait for tasks to end. Get the list of cmd.exe windows with window title 
rem to see the state of the task

rem Tasks in working state indicate master needs to keep working
rem Tasks in ended state have the return value in the window title and are 
rem waiting for the master to retrieve the value and end them

:wait
    set "keepWaiting="

    for /f "tokens=9 delims=," %%a in ('tasklist /fi "imagename eq cmd.exe" /fo csv /v ^| findstr /l /c:"[task];%taskPrefix%"'
    ) do for /f "tokens=2-4 delims=;" %%b in ("%%a") do (
        if "%%c"=="working" (
            set "keepWaiting=1"
        ) else if "%%c"=="ended" (
            set "return[%%b]=%%d"
            start "" /min waitfor.exe /si %%b
        )
    )

rem If any task has been found in working state, keep waiting
    if defined keepWaiting (
        echo %time% : waiting ...
        timeout /t 5 > nul 
        goto wait
    )

rem All tasks have ended. Show return values
    for /l %%a in (1 1 %numTasks%) do (
        echo task #%%a ended with exit value :[!return[%taskPrefix%%%a]!]
    )

    endlocal
master.cmd

@echo off
    setlocal

rem Retrieve task information and set window title    
    set "taskID=%~1"
    title [task];%taskID%;working;

rem Retrieve the rest of parameters. For this sample, a random value
    set /a "timeToWait=%~2 %% 30"

rem Simulate command processing
    timeout /t %timeToWait%

rem Calculate a return value for this task
    for /f "tokens=1-10 delims=,.:/ " %%a in ("%date%%time%_%~2") do set "returnValue=%%a%%b%%c%%d%%e%%f%%g%%h%%i%%j"

rem Signal the end of the task
    title [task];%taskID%;ended; my return value is %returnValue% ;

rem Wait for master to end this tasks
    cls
    echo Waiting for master....
    waitfor %taskID%

rem Cleanup    
    endlocal
@echo off

    setlocal enableextensions enabledelayedexpansion

rem Configure tasks
    set "taskPrefix=myTSK"
    set "numTasks=5"

rem Start tasks
    for /l %%a in (1 1 %numTasks%) do (
        set "return[%taskPrefix%%%a]=unknown"
        start "[task];%taskPrefix%%%a;working;" cmd /c "task.cmd %taskPrefix%%%a !random!"
    )

rem Wait for tasks to start    
    timeout /t 2 > nul

rem Wait for tasks to end. Get the list of cmd.exe windows with window title 
rem to see the state of the task

rem Tasks in working state indicate master needs to keep working
rem Tasks in ended state have the return value in the window title and are 
rem waiting for the master to retrieve the value and end them

:wait
    set "keepWaiting="

    for /f "tokens=9 delims=," %%a in ('tasklist /fi "imagename eq cmd.exe" /fo csv /v ^| findstr /l /c:"[task];%taskPrefix%"'
    ) do for /f "tokens=2-4 delims=;" %%b in ("%%a") do (
        if "%%c"=="working" (
            set "keepWaiting=1"
        ) else if "%%c"=="ended" (
            set "return[%%b]=%%d"
            start "" /min waitfor.exe /si %%b
        )
    )

rem If any task has been found in working state, keep waiting
    if defined keepWaiting (
        echo %time% : waiting ...
        timeout /t 5 > nul 
        goto wait
    )

rem All tasks have ended. Show return values
    for /l %%a in (1 1 %numTasks%) do (
        echo task #%%a ended with exit value :[!return[%taskPrefix%%%a]!]
    )

    endlocal

在本示例中,任务使用
waitfor
命令等待master。在XP中,这是不可用的,只需暂停即可替换,并且从
master.cmd
必须修改等待循环,将processID标记包含在
任务列表
处理中,以便使用
taskkill
+1关闭等待任务,我正在写同样的答案:)除了我会使用SET/P来读取临时文件而不是FOR/F(抱歉,我来不及编辑我的第一条评论)非常感谢你们两位,FOR/F和SET/P都能完美地工作!出于好奇,这两者之间有什么区别?据我所知,即使是传递和解析多个变量,两者都会产生相同的结果。(对于一行,对于集合,每行一个变量)对于/f
;它更详细,但允许处理多个输入行<代码>设置/p
更紧凑,但必须进行引导,以允许多个输入。在目前的情况下,没有实际的区别,因为您只处理一行。西红柿/西红柿。选择或风格的问题。