在一秒钟内延迟批处理文件?

时间:2015-04-19 16:54:34

标签: batch-file

有没有办法在一秒钟内延迟批处理文件,例如10毫秒?

我试着写这个:

ping localhost -n 1 -w 10

但它不起作用

有人可以帮忙吗?

6 个答案:

答案 0 :(得分:6)

前一段时间I posted a method提供精确定时,延迟间隔为15毫秒。这是整个帖子的副本。


我认为当延迟很小时,我在精确定时时实现了毫秒延迟。我使用了带有WScript.Sleep方法的混合Batch-JScript解决方案,但为了避免每次使用时JScript部分的加载延迟,两个部分必须同时处于活动状态。 JScript进程以毫秒为延迟,执行延迟并向Batch部分发送信号。批处理过程向JScript发送毫秒数并等待信号。实现这种双向通信的方法是通过JScript的WshShwll.Exec方法,该方法可以访问批处理过程' Stdin和Stdout流。

@if (@CodeSection == @Batch) @then


@echo off
setlocal EnableDelayedExpansion
if defined restart goto secondPart

rem First part: execute JScript section, so it re-execute this Batch file
set restart=true
CScript //nologo //E:JScript "%~F0" "%~F0"
goto :EOF

:secondPart

rem To do a delay, use: "echo #millisecs" followed by "set /P ="; use "echo 0" to end
rem To display data in the screen, use:  echo data > CON
rem To read data from keyboard, use set /P "data=Prompt: " < CON > CON

set runs=10
For %%t in (5 10 15 20 30 50 100 250 500 1000) do (

   set time_idle_ms=%%t
   (
   set t0=!time!
   for /L %%p in (1,1,%runs%) do echo %%t& set /P =
   set t1=!time!
   )

   for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
      set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
   )

   set /a average_time=a*10/runs
   echo(Input:!time_idle_ms! ms - Output: Average time !average_time! ms > CON
)

rem Send the signal to end JScript section
echo 0
goto :EOF


@end


// JScript section

// Restart this Batch file with access to its Stdin and Stdout streams
var WshShell = new ActiveXObject("WScript.Shell");
var BatchFile = WshShell.Exec('"'+WScript.Arguments(0)+'"'), delay;

// Get delay, wait and send CR until delay equ 0
while ((delay = BatchFile.Stdout.ReadLine()) != "0" ) {
   WScript.Sleep(delay);
   BatchFile.Stdin.WriteLine();
}

输出:

Input:5 ms - Output: Average time 15 ms
Input:10 ms - Output: Average time 16 ms
Input:15 ms - Output: Average time 15 ms
Input:20 ms - Output: Average time 32 ms
Input:30 ms - Output: Average time 31 ms
Input:50 ms - Output: Average time 63 ms
Input:100 ms - Output: Average time 109 ms
Input:250 ms - Output: Average time 250 ms
Input:500 ms - Output: Average time 500 ms
Input:1000 ms - Output: Average time 1000 ms

Windows 8.1中的另一项测试32位--3.2 GHz

Input:5 ms - Output: Average time 14 ms
Input:10 ms - Output: Average time 16 ms
Input:15 ms - Output: Average time 15 ms
Input:20 ms - Output: Average time 31 ms
Input:30 ms - Output: Average time 32 ms
Input:50 ms - Output: Average time 61 ms
Input:100 ms - Output: Average time 110 ms
Input:250 ms - Output: Average time 250 ms
Input:500 ms - Output: Average time 501 ms
Input:1000 ms - Output: Average time 1000 ms

编辑pathping测试已添加

为了完成这个主题,我使用pathping进行了时序测试,并使用相同的代码来测试我的方法。这是:

@echo off
setlocal EnableDelayedExpansion

set runs=10
For %%t in (5 10 15 20 30 50 100 250 500 1000) do (

   set time_idle_ms=%%t
   (
   set t0=!time!
   for /L %%p in (1,1,%runs%) do pathping 127.0.0.1 -n -q 1 -p %%t >nul
   set t1=!time!
   )

   for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
      set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
   )

   set /a average_time=a*10/runs
   echo(Input:!time_idle_ms! ms - Output: Average time !average_time! ms

)

结果显示pathping 可靠的小延迟时间:

Input:5 ms - Output: Average time 48 ms
Input:10 ms - Output: Average time 47 ms
Input:15 ms - Output: Average time 47 ms
Input:20 ms - Output: Average time 62 ms
Input:30 ms - Output: Average time 63 ms
Input:50 ms - Output: Average time 93 ms
Input:100 ms - Output: Average time 141 ms
Input:250 ms - Output: Average time 281 ms
Input:500 ms - Output: Average time 532 ms
Input:1000 ms - Output: Average time 1031 ms

答案 1 :(得分:2)

pathping 127.0.0.1 -n -q 1 -p 100 >nul

Here是关于正确等待/延迟的讨论,以毫秒为单位。根据最后的帖子,路径应该以毫秒为单位进行工作。

答案 2 :(得分:1)

下面我有三种不同的纯脚本解决方案,用于在批处理脚本中提供亚秒级延迟。所有这些解决方案都具有因机器而异的最小延迟。只要超过最小延迟,它们通常都精确到10毫秒内。

我使用Aacini的测试工具来测试所有三种方法的准确性,以便将结果直接与他的结果进行比较。


批量宏

这种纯批次解决方案在概念上非常简单。我得到当前时间(精度为1/100秒),添加延迟,并在紧密循环中等待新时间。

我已将此逻辑打包在高级批量宏技术中,这种技术难以理解和开发,但易于使用。通过使用宏,CALL没有引入延迟。如果您想了解有关批量宏观理论的更多信息以及如何编写自己的理论,请参阅Current batch macro syntaxhistorical development of batch macros

这种纯批量解决方案具有三者中最小的最小延迟。在我测试的两台机器上,最小延迟范围从约15到约30毫秒。此宏仅支持不到24小时的延迟。

这个宏的主要缺点是消耗了CPU资源 - 将单个核心的单个CPU机器与整个延迟的100%使用率挂钩。

@echo off
setlocal disableDelayedExpansion

::********  Define the @delay macro  ****************

:: define LF as a Line Feed (newline) character
set ^"LF=^

^" Above empty line is required - do not remove

:: define a newline with line continuation
set ^"\n=^^^%LF%%LF%^%LF%%LF%^^"

set @delay=for %%# in (1 2) do if %%#==2 (%\n%
  for /f "tokens=1-4 delims=:.," %%a in ("!time: =0!") do set /a "t1=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100, arg1/=10"%\n%
  cmd /v:on /c for /l %%. in (^^^) do @for /f "tokens=1-4 delims=:.," %%a in ("^!time: =0^!"^^^) do @set /a "t2=(((1%%a*60)+1%%b)*60+1%%c)*100+1%%d-36610100,tDiff=t2-t1"^^^>nul^^^&(if ^^^^!tDiff^^^^! lss 0 set /a tDiff+=8640000^^^>nul^^^)^^^&if ^^^^!tDiff^^^^! geq ^^^^!arg1^^^^! exit%\n%
  endlocal%\n%
) else setlocal enableDelayedExpansion^&set arg1=


::**********  Demonstrate usage  ********************
echo Delaying for 1.25 seconds ...
%@delay% 1250
echo done.
echo(


::***********  Testing accuracy  ********************
setlocal enableDelayedExpansion
echo Testing accuracy:
set runs=10
for %%t in (10 20 30 40 50 70 100 250 500 1000) do (

  (
  set t0=!time!
  for /l %%p in (1,1,%runs%) do %@delay% %%t
  set t1=!time!
  )

  for /f "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
    set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
  )

  set /a average_time=a*10/runs
  echo(Input:%%t ms - Output: Average time !average_time! ms
)

- 样本结果 -

Delaying for 1.25 seconds ...
done.

Testing accuracy:
Input:10 ms - Output: Average time 14 ms
Input:20 ms - Output: Average time 20 ms
Input:30 ms - Output: Average time 30 ms
Input:40 ms - Output: Average time 40 ms
Input:50 ms - Output: Average time 50 ms
Input:70 ms - Output: Average time 70 ms
Input:100 ms - Output: Average time 100 ms
Input:250 ms - Output: Average time 250 ms
Input:500 ms - Output: Average time 500 ms
Input:1000 ms - Output: Average time 1000 ms


SLEEP.BAT - 混合JScript /批处理(区域不可知)

这是我最喜欢的解决方案。我打电话给我的SLEEP.BAT实用程序,传递所需的延迟,加上CALL时的当前%time%。批处理脚本调用嵌入在同一文件中的JScript,从当前时间减去CALL时间以确定已经过了多长时间,然后从延迟时间中减去此值以确定脚本应该休眠多长时间。此解决方案使用WScript.sleep()方法,该方法是事件驱动的,不消耗CPU资源。

如果没有传入,批处理脚本将提供自己的%time%值,但由于调用该实用程序所需的时间长度,准确性可能会受到影响。

CSCRIPT初始化需要很长时间,因此最小延迟比宏解决方案更长。在我的两台机器上,最小延迟范围从约30到约55毫秒。

SLEEP.BAT应该可以在任何Windows计算机上运行,​​无论您的语言环境如何显示日期和时间。我对这个实用程序唯一的问题是,如果在从标准时间转换为夏令时之前调用瞬间,它可以给出错误的延迟,反之亦然。反之亦然。

<强> SLEEP.BAT

@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScript comment
@goto :batch
:::
:::SLEEP.BAT  msec  [%time%]
:::SLEEP.BAT  /?
:::
:::  Suspend processing for msec milliseconds. The optional %time% argument
:::  can be added to improve timing accuracy. If called within a FOR loop,
:::  then !time! should be used instead, after enabling delayed expansion.
:::
:::  There is a startup time for SLEEP.BAT that limits the shortest delay
:::  possible. The startup time varies from machine to machine. Delays longer
:::  than the minimum are usually accurate to within 10 msec if the %time%
:::  argument is provided. One exception is when SLEEP.BAT is called the
:::  instant before changing from standard to daylight savings time, in which
:::  case the delay is extended by the startup time. The other exception occurs
:::  when changing from daylight savings to standard, in which case the delay
:::  never exceeds the startup time.
:::
:::  A single /? argument displays this help.
:::
:::  SLEEP.BAT Version 1.0 - written by Dave Benham
:::

============= :Batch portion ===========
@echo off
if "%~1" equ "/?" (
  for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do @echo(%%A
  exit /b 0
) else cscript //E:JScript //nologo "%~f0" %* %time%
exit /b

============ JScript portion ==========*/
try {
  var arg2 = WScript.Arguments.Item(1).split(/[:.,]/);
  var start = new Date();
  if (start.getHours()<Number(arg2[0])) start.setDate( start.getDate()-1 );
  start.setHours( Number(arg2[0]),
                  Number(arg2[1]),
                  Number(arg2[2]),
                  Number(arg2[3])*10
                );
  var delay = Number(WScript.Arguments.Item(0));
  var adjustedDelay = delay - ((new Date())-start);
  if (adjustedDelay>0) WScript.sleep( (adjustedDelay>delay) ? delay : adjustedDelay );
  WScript.Quit(0);
} catch(e) {
  WScript.Stderr.WriteLine("SLEEP.BAT - Invalid call");
  WScript.Quit(1);
}

测试工具和使用说明

@echo off
setlocal enableDelayedExpansion
set runs=10
for %%t in (20 30 40 50 70 100 250 500 1000) do (

  (
  set t0=!time!
  for /l %%p in (1,1,%runs%) do call sleep %%t !time!
  set t1=!time!
  )

  for /f "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
    set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
  )

  set /a average_time=a*10/runs
  echo(Input:%%t ms - Output: Average time !average_time! ms
)

- 样本输出 -

Input:20 ms - Output: Average time 56 ms
Input:30 ms - Output: Average time 55 ms
Input:40 ms - Output: Average time 54 ms
Input:50 ms - Output: Average time 56 ms
Input:70 ms - Output: Average time 71 ms
Input:100 ms - Output: Average time 100 ms
Input:250 ms - Output: Average time 253 ms
Input:500 ms - Output: Average time 501 ms
Input:1000 ms - Output: Average time 1001 ms


LocaleSleep.bat - 混合JScript /批处理(区域设置相关)

这几乎与SLEEP.BAT完全相同,只是它传入"%date% %time%"而不是"%time%。优点是标准和夏令时之间的转换不再存在问题。主要缺点是它依赖于语言环境。只有在Date对象parse()方法正确解析%date%时,它才有效。我知道这应该适用于大多数美国机器以及其他一些机器。可以编写变体来支持其他语言环境,但每个语言环境都依赖于语言环境。

<强> LocaleSleep.bat

@if (@X)==(@Y) @end /* harmless hybrid line that begins a JScript comment
@goto :batch
:::
:::LocaleSleep.bat  msec  ["%date% %time%"]
:::LocaleSleep.bat  /?
:::
:::  Suspend processing for msec milliseconds. The optional "%date% %time%"
:::  argument can be added to improve timing accuracy. If called within a
:::  FOR loop, then "!date! !time!" should be used instead, after enabling
:::  delayed expansion.
:::
:::  This utility is locale specific. It only works properly if %date% is in
:::  a format that is parsed properly by the Date object parse() method.
:::
:::  There is a startup time for SLEEP.BAT that limits the shortest delay
:::  possible. The startup time varies from machine to machine. Delays longer
:::  than the minimum are usually accurate to within 10 msec if the
:::  "%date% %time%" argument is provided.
:::
:::  A single /? argument displays this help.
:::
:::  LocaleSleep.bat Version 1.0 - written by Dave Benham
:::

============= :Batch portion ===========
@echo off
if "%~1" equ "/?" (
  for /f "tokens=* delims=:" %%A in ('findstr "^:::" "%~f0"') do @echo(%%A
  exit /b 0
) else cscript //E:JScript //nologo "%~f0" %* "%date% %time%"
exit /b

============ JScript portion ==========*/
try {
  var arg2 = WScript.Arguments.Item(1);
  var delay = Number(WScript.Arguments.Item(0)) - ((new Date())-(new Date(arg2.slice(0,-3))).setMilliseconds( Number(arg2.slice(-2))*10 ));
  if (delay>0) WScript.sleep(delay);
  WScript.Quit(0);
} catch(e) {
  WScript.Stderr.WriteLine("localeSleep.bat - Invalid call");
  WScript.Quit(1);
}

测试工具和使用说明

@echo off
setlocal enableDelayedExpansion
set runs=10
for %%t in (20 30 40 50 70 100 250 500 1000) do (

  (
  set t0=!time!
  for /l %%p in (1,1,%runs%) do call localeSleep %%t "!date! !time!"
  set t1=!time!
  )

  for /f "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!t1: =0!") do (
    set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000"
  )

  set /a average_time=a*10/runs
  echo(Input:%%t ms - Output: Average time !average_time! ms
)

结果与SLEEP.BAT几乎完全相同

答案 3 :(得分:1)

Here's how!


  1. Here's an image of it
  2. If that link didn't work try this

    pathping 127.0.0.1 -n -q 1 -p 100> nul

我建议改用{% if user_settings.room2 %} <li><a href="/{{ user_settings.room2 }}" id="room2">/{{ user_settings.room2 }}</a></li> {% endif %} localhost

  

或者尝试pathping localhost -n -q 1 -p 100 >nul等待timeout %seconds% /nobreak >nul && pathping localhost -n -q 1 -p %extra% >nul秒和%seconds%的时间


%extra%意味着将两个代码放在一行上,就像两行一样!

但是&&意味着要运行第一个代码,如果同样失败,也要运行第二个代码,但是如果第一个代码成功,则不要运行第二个代码

您可以使用||

对代码进行分组

所以(%code%)意味着要运行(%code1%)||(%code2%&&%code3%),如果运行失败,则运行%code1%%code2%


这是我制作的“快速”代码段,说明其工作原理:

%code3%
var a=document.getElementById("countdown");
var b=document.getElementById("full");
var c=document.getElementById("text");
var e=document.getElementById("timeout");
function end(){
  if(!d){
    c.innerHTML="press CTRL+C to stop"
    a.innerHTML="10";
    e.innerHTML="/nobreak"
    d=true;
  }else{
    b.remove();
  }
}
var d=false;
setInterval(function(){
  try{
    if(a.innerHTML<=0){
      end();
    }
    a.innerHTML=a.innerHTML>0?a.innerHTML-1:a.innerHTML;
  }catch(err){}
},1000);


  • (我不知道时间<span id="full"> &gt; <code>timeout 10 <span id="timeout"></span></code><br> <span>Waiting for <span id="countdown">10</span> seconds, <span id="text">press <input type="button" value="Any key" onclick="if(!d){end();}"></span> to continue . . .</span><br> </span>的时间单位)

答案 4 :(得分:0)

Windows Server 2003 Resource Kit Tools有一个sleep.exe部分,你可以用毫秒来指定睡眠时间:

{
    "personWrapper":
    {
        "_Id":"<ID HERE (MIGHT WANT SQL TO GENERATE THIS DURING CREATE>",
        "leader":{
            "_Id":"<ID HERE (MIGHT WANT SQL TO GENERATE THIS DURING CREATE>",
            "name":"Leader McLeaderFace"
        },
        delegates:[{...},{...},{...}]
    }
}

答案 5 :(得分:0)

如果您在Windows上,请编译以下C程序,并将其命名为sleep.exe。如果要睡眠100毫秒,请输入以下命令:

睡眠100

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <Windows.h>

int main(int argc, char* argv[])
{
    int n = atoi(argv[1]);
    Sleep(n);
    return 0;
}