```html Threading in Windows Forms (VB) – MSDN

Threading in Windows Forms (VB)

Overview

Windows Forms controls are bound to a single UI thread. Performing long‑running operations on this thread blocks the UI, causing the application to become unresponsive. Proper threading techniques allow you to keep the UI responsive while executing background work.

Using BackgroundWorker

The BackgroundWorker component simplifies executing code on a separate thread and reporting progress back to the UI.

Imports System.ComponentModel

Public Class Form1
    Private WithEvents bw As New BackgroundWorker

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        bw.WorkerReportsProgress = True
        bw.WorkerSupportsCancellation = True
    End Sub

    Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
        If Not bw.IsBusy Then bw.RunWorkerAsync()
    End Sub

    Private Sub bw_DoWork(sender As Object, e As DoWorkEventArgs) Handles bw.DoWork
        For i As Integer = 1 To 100
            If bw.CancellationPending Then
                e.Cancel = True
                Exit For
            End If
            System.Threading.Thread.Sleep(50)   ' Simulate work
            bw.ReportProgress(i)
        Next
    End Sub

    Private Sub bw_ProgressChanged(sender As Object, e As ProgressChangedEventArgs) Handles bw.ProgressChanged
        progressBar.Value = e.ProgressPercentage
        lblStatus.Text = $"Progress: {e.ProgressPercentage}%"
    End Sub

    Private Sub bw_RunWorkerCompleted(sender As Object, e As RunWorkerCompletedEventArgs) Handles bw.RunWorkerCompleted
        If e.Cancelled Then
            lblStatus.Text = "Cancelled"
        ElseIf e.Error IsNot Nothing Then
            lblStatus.Text = $"Error: {e.Error.Message}"
        Else
            lblStatus.Text = "Completed!"
        End If
    End Sub
End Class

Using Task and Await

For .NET 4.5+ you can leverage Task with async/await to keep code concise.

Imports System.Threading.Tasks

Public Class Form1
    Private Async Sub btnLoadData_Click(sender As Object, e As EventArgs) Handles btnLoadData.Click
        btnLoadData.Enabled = False
        progressBar.Style = ProgressBarStyle.Marquee
        Try
            Dim result As String = Await Task.Run(Function()
                                                      ' Simulate long work
                                                      System.Threading.Thread.Sleep(2000)
                                                      Return "Data loaded"
                                                  End Function)
            lblResult.Text = result
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        Finally
            btnLoadData.Enabled = True
            progressBar.Style = ProgressBarStyle.Blocks
        End Try
    End Sub
End Class

Invoking the UI Thread

If you must update a control from a background thread, use Control.Invoke (or BeginInvoke).

Private Sub DoWork()
    ' Running on a background thread
    Dim text As String = GetData()
    If lblResult.InvokeRequired Then
        lblResult.Invoke(Sub() lblResult.Text = text)
    Else
        lblResult.Text = text
    End If
End Sub

Best Practices

ScenarioRecommended Approach
Simple background work with progress reportingBackgroundWorker
Modern async code, .NET 4.5+Task + async/await
Need to update UI from non‑UI threadControl.Invoke/BeginInvoke or SynchronizationContext
Cancellation supportCancellationTokenSource with Task

Further Reading

```