'delay a batch file in under a second?

Is there any way to delay a batch file in under a second, for example 10 milliseconds?

I have tried to write this:

ping localhost -n 1 -w 10

But it didn't work

Can anyone help?



Solution 1:[1]

Some time ago I posted a method that gives precise timing with delay intervals from 15 milliseconds on. This is a copy of the entire post.


I think I achieved a milliseconds delay with precise timing when the delay is small. I used an hybrid Batch-JScript solution with WScript.Sleep method, but in order to avoid the load delay of the JScript section each time it is used, both parts must be active at same time. The JScript process take the delay in milliseconds, do the delay and send a signal to the Batch section. The Batch process send the number of milliseconds to JScript and wait for the signal. The way to achieve this bi-directional communication is via JScript's WshShwll.Exec method that have access to Batch process' Stdin and Stdout streams.

@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();
}

Output:

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

Another test in Windows 8.1 32 bit - 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

EDIT: pathping test added

Just to complete this topic, I did a timing test using pathping and the same code used to test my method. Here it is:

@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

)

The result show that pathping is not reliable for small delay times:

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

Solution 2:[2]

Below I have three different pure script solutions for providing sub-second delays within a batch script. All of these solutions have a minimum delay that varies from machine to machine. As long as the minimum delay is exceeded, they each are generally accurate to within 10 milliseconds.

I used Aacini's test harness to test the accuracy of all three methods so the results can be compared directly with his results.


Batch Macro

This pure batch solution is very simple in concept. I get the current time (with 1/100 second precision), add the delay, and wait for that new time within a tight loop.

I've packaged this logic in an advanced batch macro technique that is tricky to understand and develop, but easy to use. By using a macro, there is no delay introduced by CALL. See Current batch macro syntax and historical development of batch macros if you want to learn more about batch macro theory, and how to write your own.

This pure batch solution has the smallest minimum delay of the three. On the two machines I've tested, the minimum delay ranged from ~15 to ~30 msec. This macro only supports delays less than 24 hours.

The major drawback with this macro is it consumes CPU resources - pegging a single CPU machine with a single core to 100% usage throughout the delay.

@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
)

-- Sample results --

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 - Hybrid JScript/Batch (Locale Agnostic)

This is my favorite solution. I CALL my SLEEP.BAT utility, passing in the desired delay, plus the current %time% at the time of the CALL. The batch script calls JScript embedded within the same file, which subtracts the CALL time from the current time to determine how much time has already elapsed, and then subtracts this value from the delay time to figure out how long the script should sleep. This solution uses the WScript.sleep() method, which is event driven and does not consume CPU resources.

The batch script will supply its own %time% value if it is not passed in, but then the accuracy may suffer a bit due to the length of time it takes to CALL the utility.

It takes a significant time for CSCRIPT to initialize, so the minimum delay is longer than the macro solution. On my two machines, the minimum delay ranged from ~30 to ~55 msec.

SLEEP.BAT should work on any Windows machine, regardless how your locale displays date and time. The only problem I have with this utility is it can give the wrong delay if called the instant before changeover from standard to daylight savings time, or vice-versa.

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);
}

Test harness and demonstration of usage

@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
)

-- Sample Output --

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 - Hybrid JScript/Batch (Locale Dependent)

This is nearly identical to SLEEP.BAT, except it passes in "%date% %time%" instead of "%time%. The advantage is it no longer has problems with the changeover between standard and daylight savings time. The major disadvantage is it is locale dependent. It only works if %date% is parsed properly by the Date object parse() method. I know this should work on most U.S. machines, plus some others. Variants could be written to support other locales, but each would be locale dependent.

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);
}

Test harness and demonstration of usage

@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
)

Results are virtually identical to SLEEP.BAT

Solution 3:[3]

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

Here was a discussion about proper wait/delay in milliseconds.According to the last posts pathping should do the work for the milliseconds.

with mshta (this will wait 500 milliseconds):

start "" /wait /min /realtime mshta "javascript:setTimeout(function(){close();},500)"

Another way with selfcompiled .NET executable:

@if (@X)==(@Y) @end /* JScript comment
@echo off
setlocal
::del %~n0.exe /q /f
::
:: For precision better call this like
:: call waitMS 500
:: in order to skip compilation in case there's already built .exe
:: as without pointed extension first the .exe will be called due to the ordering in PATEXT variable
::
::
for /f "tokens=* delims=" %%v in ('dir /b /s /a:-d  /o:-n "%SystemRoot%\Microsoft.NET\Framework\*jsc.exe"') do (
   set "jsc=%%v"
)

if not exist "%~n0.exe" (
    "%jsc%" /nologo /w:0 /out:"%~n0.exe" "%~dpsfnx0"
)


%~n0.exe %*

endlocal & exit /b %errorlevel%


*/


import System;
import System.Threading;

var arguments:String[] = Environment.GetCommandLineArgs();
function printHelp(){
    Console.WriteLine(arguments[0]+" N");
    Console.WriteLine(" N - milliseconds to wait");
    Environment.Exit(0);    
}

if(arguments.length<2){
    printHelp();
}

try{
    var wait:Int32=Int32.Parse(arguments[1]);
    System.Threading.Thread.Sleep(wait);
}catch(err){
    Console.WriteLine('Invalid Number passed');
    Environment.Exit(1);
}

Solution 4:[4]

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

I recommend using localhost instead, pathping localhost -n -q 1 -p 100 >nul!

Or try timeout %seconds% /nobreak >nul && pathping localhost -n -q 1 -p %extra% >nul to wait %seconds% seconds, and %extra% amount of time


The && means to put two codes on 1 line, acting like 2 lines!

But || means to run the first code, if that fails run the second code too, but if the first code succeeds then don't run the second code

And you can group code with (%code%)

So (%code1%)||(%code2%&&%code3%) means to run %code1%, if that fails run %code2% and %code3% after that!


Here is a "quick" snippet I made, on how it works:

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>

  • (I don't know what measurement of time %extra% is in)

Solution 5:[5]

Pause for 1/100th of a second!

This code works in Windows 10, and Probably earlier versions back to XP, is 100% true batch/CMD, and uses no VBScript, PowerShell, EXE, etc...

Set Centiseconds:

  1. To 100 for a full second pause.
  2. To 50 for a half second pause.
  3. To 25 for a quarter of a second pause.
  4. To 10 for a 1/10th, or 10%, of a second pause.
  5. To 5 for a 1/20th, or 5%, of a second pause.
  6. To n for a n/100th of a second pause.
  7. To 1, as in example below, for 1/100th of a second pause.
    SET Centiseconds=1
    SET "NOWTIME=%TIME:00.=%"
    SET "NOWTIME=%NOWTIME:.=%"
    FOR /F "TOKENS=1-3 DELIMS=:" %%G IN ("%NOWTIME::0=:%") DO SET /A "StartCentiseconds=(%%G*60+%%H)*6000+%%I"
    SET /A EndCentiseconds=StartCentiseconds+Centiseconds
:GetNow
    SET "NOWTIME=%TIME:00.=%"
    SET "NOWTIME=%NOWTIME:.=%"
    FOR /F "TOKENS=1-3 DELIMS=:" %%G IN ("%NOWTIME::0=:%") DO SET /A "NowCentiseconds=(%%G*60+%%H)*6000+%%I"
    IF %NowCentiseconds% LSS %StartCentiseconds% SET /A NowCentiseconds=NowCentiseconds+8640000
    IF %NowCentiseconds% LSS %EndCentiseconds% GOTO :GetNow

For debuging, you can use the following to check values of variables:

    ECHO;[%StartCentiseconds%]
    ECHO;[%EndCentiseconds%]
    ECHO;[%NowCentiseconds%]

The code calculates centi-seconds since midnight by removing the period provided by %Time%, then removes zeros after colons so numbers are not interpreted as hexadecimal, splits by colons, and then does the needed math.

EDIT:

Found error when seconds equal 00.nn, fixed by replacing SET "NOWTIME=%TIME:.=%" with lines SET "NOWTIME=%TIME:00.=%" and SET "NOWTIME=%NOWTIME:.=%"

Reliability Testing:

The following code:

  1. Enables Delayed Expansion of variables so variables inside parentheses will be accessible by using !MyVar! instead of %MyVar%.
  2. Loops through each possible hour of a day (0 to 23), each possible minutes of each hour (0 to 59), each possible second of each minute (0 to 59), and each possible centisecond of each second (0 to 100).
  3. For each centisecond, variable Counter is used to count centiseconds since hour 0, minute 0, second 0, and centisecond 0.
  4. For each centisecond, the current hour, minute, second, and centisecond is used to build a time string that is in the format that %TIME% returns, and save it to the variable NOWTIME.
  5. For each centisecond, the time string in NOWTIME is converted to the current centisecond using code based on the above code example.
  6. For every 100,000 centiseconds, a simple {n00000=n00000} message is echoed to the screen. This can be used to estimate how long the program will run since the last message echoed should be {8600000=8600000}. For example, on one computer it took 34 seconds between each of these messages so I knew the total time was about 86 messages * 34 seconds per message / 60 seconds per minute, or near 49 minutes to run.
  7. If the calculated centisecond derived from NOWTIME ever fails to match Counter, then an error messages is displayed.
@ECHO OFF
    SetLocal EnableDelayedExpansion

    SET "Counter=0"
    FOR /L %%H IN (0,1,23) DO (
        SET Hour= %%H
        SET Hour=!Hour:~-2!
        FOR /L %%M IN (0,1,59) DO (
            SET Minute=0%%M
            SET Minute=!Minute:~-2!
            FOR /L %%S IN (0,1,59) DO (
                SET Second=0%%S
                SET Second=!Second:~-2!
                FOR /L %%C IN (0,1,99) DO (
                    SET Centisecond=0%%C
                    SET Centisecond=!Centisecond:~-2!
                    SET NOWTIME=!Hour!:!Minute!:!Second!.!Centisecond!
                    SET "NOWTIME=!NOWTIME:00.=!"
                    SET "NOWTIME=!NOWTIME:.=!"
                    FOR /F "TOKENS=1-3 DELIMS=:" %%G IN ("!NOWTIME::0=:!") DO SET /A "Centiseconds=(%%G*60+%%H)*6000+%%I"
                    if !Counter:~-5! EQU 0 ECHO;{!Centiseconds!=!Counter!}
                    IF !Centiseconds! NEQ !Counter! ECHO;ERROR: Calculated centisecond !Centiseconds! does not match Counter's centisecond !Counter!.
                    SET /A Counter=Counter+1
                )
            )
        )
    )

Very Annoying Example of Use

I advise against using this in actual code, this is for demonstration purpose only. This code clears the screen, post a fake error message, flashes/strobes screen with 3 evenly timed flashes, 7 short flashes with longer waits, and then 10 changes in color.

@ECHO OFF
    SETLOCAL EnableDelayedExpansion
GOTO :Start

@REM Parameters: VariableName [OptionalVariableName] {Value} [{OptionalValue}] ### Description

@REM :GetCentisecondsSinceMidnight Returned CentisecondsSinceMidnight [{LastCentiseconds}] ### Returns the number of centiseconds since midnight.
:GetCentisecondsSinceMidnight
    IF "%~1" EQU "" ECHO;ERROR: GetCentisecondsSinceMidnight - missing parameter CentisecondsSinceMidnight. & GOTO :EOF
    SET "NOWTIME=%TIME:00.=%"
    SET "NOWTIME=%NOWTIME:.=%"
    FOR /F "TOKENS=1-3 DELIMS=:" %%G IN ("%NOWTIME::0=:%") DO SET /A "Centiseconds=(%%G*60+%%H)*6000+%%I"
    @REM If LastCentiseconds is available, 
    @REM     then check if went past midnight boundary, and if so, add 1 days worth of centiseconds.
    IF "%~2" NEQ "" IF %Centiseconds% LSS %~2% SET /A Centiseconds+=8640000
    SET "%~1=%Centiseconds%"
GOTO :EOF

@REM :WaitCentiseconds {CentisecondsToWait} ### Waits Centiseconds.
:WaitCentiseconds
    IF "%~1" EQU "" ECHO;ERROR: WaitCentiseconds - missing parameter CentisecondsToWait. & GOTO :EOF
    CALL :GetCentisecondsSinceMidnight StartCentiseconds
    SET /A EndCentiseconds=StartCentiseconds+%~1
:LoopInWaitCentiseconds
    CALL :GetCentisecondsSinceMidnight NowCentiseconds %StartCentiseconds%
    IF %NowCentiseconds% LSS %EndCentiseconds% GOTO :LoopInWaitCentiseconds
GOTO :EOF

@REM FlashScreen {ForCentiseconds} ### Flash screen ForCentiseconds.
:FlashScreen
    IF "%~1" EQU "" ECHO;ERROR: FlashScreen - missing parameter ForCentiseconds. & GOTO :EOF
    COLOR F0
    CALL :WaitCentiseconds %~1
    COLOR 0F
GOTO :EOF

@REM StrobeScreen {NumberOfStrobs} {OnWait} [{OffWait}] ### Strobes NumberOfStrobs times, on for OnWait centiseconds, and off for OffWait if available else OnWait centiseconds.
:StrobeScreen
    IF "%~2" EQU "" ECHO;ERROR: StrobeScreen - missing parameter OnWait. & GOTO :EOF
    IF "%~1" EQU "" ECHO;ERROR: StrobeScreen - missing parameter NumberOfStrobs. & GOTO :EOF
    SET "OffWait=%~2"
    IF "%~3" NEQ "" SET "OffWait=%~3"
    IF %~1 LEQ 0 GOTO :EOF
    CALL :FlashScreen %~2
    FOR /L %%G IN (2,1,%~1) DO (
        CALL :WaitCentiseconds %OffWait%
        CALL :FlashScreen %~2
    )
GOTO :EOF

@REM :GetRandomColorCode ReturnedColorCode ### Saves color code in variable provided in ReturnedColorCode.
:GetRandomColorCode
    IF "%~1" EQU "" ECHO;ERROR: GetRandomColorCode - missing parameter ReturnedColorCode. & GOTO :EOF
    SET "ColorCodes=0123456789ABCDEF"
    SET /A "NUM=!RANDOM!%%16"
    SET "%~1=!ColorCodes:~%Num%,1!"
GOTO :EOF

@REM :RandomColorChange ### Changes both background and foreground to random color.
:RandomColorChange
    CALL :GetRandomColorCode RCC1
:LoopInRandomColorChange
    CALL :GetRandomColorCode RCC2
    IF %RCC2% EQU %RCC1% GOTO :LoopInRandomColorChange
    COLOR %RCC1%%RCC2%
GOTO :EOF

@REM :ColorStrobeScreen {NumberOfColorChanges} {CentisecondsWait} ### Randomly changes screen color NumberOfColorChanges times, for CentisecondsWait time.
:ColorStrobeScreen
    IF "%~2" EQU "" ECHO;ERROR: ColorStrobeScreen - missing parameter CentisecondsWait. & GOTO :EOF
    IF "%~1" EQU "" ECHO;ERROR: ColorStrobeScreen - missing parameter NumberOfColorChanges. & GOTO :EOF
    FOR /L %%G IN (1,1,%~1) DO (
        CALL :RandomColorChange
        CALL :WaitCentiseconds %~2
    )
    COLOR 0F
GOTO :EOF

:Start
    CLS
    ECHO;FAKE ERROR: Something when wrong
    CALL :StrobeScreen 3 20
    CALL :WaitCentiseconds 10
    CALL :StrobeScreen 7 3 50
    CALL :ColorStrobeScreen 10 15

Solution 6:[6]

There is a sleep.exe part of the Windows Server 2003 Resource Kit Tools where you can specify the sleep time in milliseconds:

? sleep /?
Usage:  sleep      time-to-sleep-in-seconds
        sleep [-m] time-to-sleep-in-milliseconds
        sleep [-c] commited-memory ratio (1%-100%)

Solution 7:[7]

If you're on windows compile the following C program and call it sleep.exe . If you want to sleep for 100 ms you give the command:

sleep 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;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3
Solution 4 Afdsafnadsjbcewjhwnfy4ntc874fg
Solution 5
Solution 6 Andreas Raster
Solution 7 Henrik4