En este ejemplo haremos una aplicación que al presionar un botón creará un thread aparte que 
"hará algo", en este caso no hará nada, solo hará tiempo, pero éste thread lanzará un evento al inicio y otro al fin de su ejecución, nosotros capturaremos esos eventos y los mostraremos en pantalla.
Como la interfaz de usuario y el thread obviamente pertenecen a distintos hilos, será necesario utilizar un Delegate con el método Invoke del control que utilizaremos, de lo contrario tendremos una 
InvalidOperationException por 
CrossThreadLo primero que haremos será asignar los manejadores a los eventos que hemos declarado anteriormente, para eso utilizaremos 
AddHandler y 
AddressOf.
#Region " Eventos de Thread y sus handlers"
    Private Event InicioThread(ByVal Inico As DateTime)
    Private Event FinThread(ByVal Fin As DateTime)
    Private Trabajando As Boolean = False
    Public Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        AddHandler InicioThread, AddressOf App_InicioThread
        AddHandler FinThread, AddressOf App_FinThread
    End Sub
    Private Sub App_InicioThread(ByVal Inicio As DateTime)
        Trabajando = True
        If TextBox1.InvokeRequired Then
            TextBox1.Invoke(New MostrarEnTextBox_Delegate(AddressOf MostrarEnTextBox), TextBox1, Inicio.ToString())
        Else
            MostrarEnTextBox(TextBox1, Inicio.ToString())
        End If
        If TextBox2.InvokeRequired Then
            TextBox2.Invoke(New MostrarEnTextBox_Delegate(AddressOf MostrarEnTextBox), TextBox2, "Todavía haciendo algo...")
        Else
            MostrarEnTextBox(TextBox2, "Todavía haciendo algo...")
        End If
    End Sub
    Private Sub App_FinThread(ByVal Fin As DateTime)
        Trabajando = False
        If TextBox2.InvokeRequired Then
            TextBox2.Invoke(New MostrarEnTextBox_Delegate(AddressOf MostrarEnTextBox), TextBox2, Fin.ToString())
        Else
            MostrarEnTextBox(TextBox2, Fin.ToString())
        End If
    End Sub
#End Region
Como se puede ver en los maejadores de eventos utilizamos un 
Delegate del método que inserta el texto en las TextBox, eso es porque requiere parámetros, sino lo hubiésemos podido hacer directamente usando 
AddressOf.
Así que lo siguiente será crear el método que ingresa texto en las TextBox y su correspondiente 
Delegate.
#Region " Delegate para Invoke "
    Private Delegate Sub MostrarEnTextBox_Delegate(ByVal txt As TextBox, ByVal str As String)
    Private Sub MostrarEnTextBox(ByVal txt As TextBox, ByVal str As String)
        txt.Text = str
    End Sub
#End Region
Como dice al principio del post, ésta aplicación tiene un botón que es el que inicia un nuevo hilo, así que agregaremos el botón y en el evento click llamaremos a un método que creará e iniciará el nuevo 
Thread. Adicionalmente, tenemos un flag para que no permitir la creación de más de un hilo por vez, su valor se cambia con los eventos del 
Thread.
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        If Not Trabajando Then
            InicializarThread()
        Else
            MessageBox.Show("Hay un 'hilo haciendo' algo aún. Intente nuevamente en unos segundos.", "Hilo trabajando", MessageBoxButtons.OK, MessageBoxIcon.Information)
        End If
    End Sub
#Region " Thread "
    Private Sub InicializarThread()
        Dim t As New Thread(AddressOf HacerAlgo)
        t.Name = "Thread_HacerAlgo"
        t.IsBackground = True
        t.Start()
    End Sub
    Private Sub HacerAlgo()
        RaiseEvent InicioThread(DateTime.Now)
        For i As Byte = 0 To 254
            Thread.Sleep(30)
        Next
        RaiseEvent FinThread(DateTime.Now)
    End Sub
#End Region
