Falta un detalle...
En bucles repetitivos (sobre todo si son largos) hay que dejar tiempo para que Windows (o el sistema operativo que se use) pueda responder las peticiones de el sistema.
Un bucle hecho de la manera que proponen no va a dejar tiempo para que el usuario interactúe con el programa. Por ejemplo: va a querer apretar el boton "Cancelar" o "Cerrar" del formulario y no lo va a permitir, además de dejar todo inoperable de tal manera que a veces hay que hacer un reset. Esta es una diferencia entre programar pics y pcs.
Cuando se usa el control Timer no hay problemas porque entre llamada y llamada del control el SO tiene tiempo de gestionar las tareas en segundo plano (incluído el Timer). Este tipo de bucles For...Next - Do...While, etc funcionan bien cuando son cortos. Cuando se trata de procesos largos hay que agregar alguna instrucción que le indique a Windows que procese los pedidos del sistema. También se usa cuando querés que se "refresque" la información de un control.
Acá van dos formas:
1) Meter en alguna parte del bucle la instrucción "DoEvents". Esto hace lo anteriormente mencionado.
2) En un módulo declarar:
Public Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
Y después en vez de usar DoEvents ponemos "Sleep 0&" (sin comillas).
Aparentemente la segunda opción es más efectiva pero suele traer problemas en algunos casos. Es cuestión de probar...