Gracias  los dos 
 
 No estoy seguro que opción es mejor pero creo que por sencillez me decanto por usar la variable boleana. 
He aprovechado para realizar un experimento de velocidad de los procesos dentro del bucle, para este ejemplo, que imagino que según el ordenador los resultados será  distinto. 
- Option Explicit On 
- Option Strict On 
- Imports System.Text 
- Public Class Form1 
-     Dim AplicacionCerrada As Boolean = False 
-     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
-         Dim stopWatch As New Stopwatch() : Dim ts As TimeSpan : Dim elapsedTime As String = Nothing 
-         Dim Cont As Integer = 0 
-   
-         stopWatch.Start() 
-         Do 
-             Cont += 1 
-             ts = stopWatch.Elapsed 
-             String.Format("{00}", ts.Seconds) 
-   
-             '///Experimeto que mide el número de procesos por segundo 
-             Dim Datos As New StringBuilder 
-             With Datos 
-                 .AppendFormat("Procesos: {0}", CInt(Cont)) 
-                 .AppendLine() 
-                 .AppendFormat("Segundos: {0}", ts.Seconds) 
-                 .AppendLine() 
-                 .AppendFormat("Velocidad: {0}", (CInt(Cont) / (CInt(ts.Seconds))).ToString("0.000") & " Proc/s") 
-             End With 
-             Label1.Text = Datos.ToString 
-             '///////////////////////////////////////////////////////////////////////// 
-   
-             If AplicacionCerrada = True Then End 
-             If ts.Seconds = 10 Then stopWatch.Stop() : Exit Do 
-             My.Application.DoEvents() 
-         Loop While Cont < 14000 
-     End Sub 
-     Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As FormClosingEventArgs) Handles MyBase.FormClosing 
-         AplicacionCerrada = True 
-     End Sub 
- End Class 
-   
Esta sería la otra forma, aunque más compleja y que me ha costado encontrar.
- Option Explicit On 
- Option Strict On 
- Imports System.Threading.Tasks 
- Imports System.Text 
-   
- Public Class Form1 
-   
-     Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
-         Dim stopWatch As New Stopwatch() : Dim ts As TimeSpan : Dim elapsedTime As String = Nothing 
-         Dim Cont As Integer = 0 
-   
-         Task.Factory.StartNew(Sub() 
-   
-                                   stopWatch.Start() 
-                                   'Desactivar el chequeo sobre acceso de varios subprocesos 
-                                   ' CheckForIllegalCrossThreadCalls = False  
-   
-                                   Do 
-                                       Cont += 1 
-                                       ts = stopWatch.Elapsed 
-                                       String.Format("{00}", ts.Seconds) 
-                                       '///Experimeto que mide el número de procesos por segundo 
-                                       Dim Datos As New StringBuilder 
-                                       With Datos 
-                                           .AppendFormat("Procesos: {0}", CInt(Cont)) 
-                                           .AppendLine() 
-                                           .AppendFormat("Segundos: {0}", ts.Seconds) 
-                                           .AppendLine() 
-                                           .AppendFormat("Velocidad: {0}", (CInt(Cont) / (CInt(ts.Seconds))).ToString("0.000") & " Proc/s") 
-                                       End With 
-                                       Label1.Invoke(CType(Sub() Label1.Text = Datos.ToString, MethodInvoker)) 
-                                       '///////////////////////////////////////////////////////////////////////// 
-                                       If ts.Seconds = 10 Then stopWatch.Stop() : Exit Do 
-                                       '  My.Application.DoEvents() 
-                                   Loop While Cont < 14000 
-   
-                               End Sub).ContinueWith(Sub() 
-                                                         Me.Invoke(Sub() 
-                                                                       Me.Text = "Proceso terminado" 
-                                                                   End Sub) 
-                                                     End Sub) 
-     End Sub 
- End Class 
-   
De esta última forma usando Task e Invoke como habéis dicho el programa se cierra sin problemas.
Me ha costado averiguar también como llamar a un control externo dentro de un subproceso, ya que si llamaba diréctamente obtenía error. La forma era la siguiente:
- Label1.Invoke(DirectCast(Sub() Label1.Text = Datos, MethodInvoker)) 
También:
-  Me.Invoke(Sub() 
-         Me.Text = "Proceso terminado" 
-         End Sub) 
En cuanto a la eficiencia creo que es lo mismo porque me dan resultados idénticos, me refiero al experimento.
Si el ordenador es al menos normalito, debería salir del bucle antes de los 10 segundos.
Saludos