【问题标题】:Avoid simultaneous call in Windows batch file避免在 Windows 批处理文件中同时调用
【发布时间】:2016-08-12 06:57:02
【问题描述】:

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

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

但是在该批次中,有一个可执行文件在并行调用时崩溃。

是否有可能使用 Windows 内置函数在该调用已经在另一个批次中运行时阻止它,并在它在另一个批次中完成时继续?

假设该批次的内容是

start delay 5

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

这类似于信号量。

所以目标是拥有这样的东西

CheckAndWaitIfDelayIsRunning
start delay 5

提前致谢。

【问题讨论】:

  • @AdrianoRepetti:start 命令没有任何选项等待另一个进程的终止...
  • @Aacini 是的,我刚刚重新阅读了这个问题,我错过了重点(等待另一个进程,而不是第二批本身终止)

标签: windows batch-file semaphore


【解决方案1】:

您可以使用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?

【讨论】:

  • 插入timeout 1 命令来降低轮询率怎么样?那行得通吗?
  • 是的,这可行,但会减慢程序反应,因为 semaLock 在等待另一个线程释放时平均会等待 0.5 秒
【解决方案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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2012-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多