避免在Windows批处理文件中同时调用

时间:2016-08-12 06:57:02

标签: windows batch-file semaphore

我有一个通用的Windows构建批处理(即build.bat),它与不同的参数并行运行。

start build.bat device1
start build.bat device2
start build.bat device3

但在该批处理中,有一个可执行文件在以并行方式调用时崩溃。

使用Windows内置函数是否可以在已经在另一个批处理中运行时阻止此调用,并在完成另一个批处理时继续执行此操作?

假设该批次的内容是

start delay 5

当多次调用批处理时,当当前正在运行另一个延迟时,延迟不得运行。

这与信号量类似。

所以我们的目标是拥有类似的东西

CheckAndWaitIfDelayIsRunning
start delay 5

提前致谢。

2 个答案:

答案 0 :(得分:6)

您可以使用lock by file批量生成信号量。

:lock
2>nul (
  > sema1.lock (
    delay 5
    REM The next line is for proper finishing the lock block
    (call )
  )
) || goto :lock

诀窍是,写入sema1.lock仅允许一次进行一个进程 任何其他进程都将失败并跳过内部块,|| goto :lock将重试,直到可以写入sema1.lock文件。
这种技术的一个缺点是消耗CPU,因为这个信号量并不是真正等待,它更像是一个轮询信号量。

有关详情,请参阅SO:How do you have shared log files under Windows?

答案 1 :(得分:2)

根据答案我优化了两件事:

  • 控制台输出仍然可见,未重定向到文件
  • %errorlevel%包含我的任务中的错误

它使用一个文件夹作为第一次创建的锁 Ping用作等待时间并设置为1000毫秒。
它计算线程等待获得执行任务的权限之前的周期数。

<强>脚本

set lockMyName="%TEMP%\my.lock"    
set lockMyCounterMs=0
set lockMyTimeMs=1000
@echo  [ INFO ] Getting my lock...
:lock_my
md %lockMyName% 2>nul
if "%errorlevel%" neq "0" (
    set /a lockMyCounterMs+=%lockMyTimeMs%
    :: commonly used timeout without waiting for input (must be invalid ip address)
    ping 1.0.0.0 -n 1 -w %lockMyTimeMs% >nul
    goto :lock_my
)
@echo  [ INFO ] ... locked ^(waited %lockMyCounterMs% ms for lock^)

 ::do your task here

@echo  [ INFO ] ...release my lock
rd /Q %lockMyName% 2>nul