Click here to Skip to main content
15,392,261 members
Articles / Programming Languages / Visual Basic
Posted 22 Mar 2011

Tagged as


38 bookmarked

Progress form in secondary thread without blocking main window

Rate me:
Please Sign up or sign in to vote.
4.47/5 (16 votes)
22 Mar 2011CPOL3 min read
This project will allow using progress forms without wrapping long processes in separate threads.


This is my first article, plus I'm not a native English speaker.. so don't be harsh on the comments please.

Very often, I have had to add a progress form in an existing function that takes longer every day because the database is growing or for other reasons. When that is the case, I need to change the code to be executed on the background so the progress form can be shown on the screen without the application showing a "Not Responding" text on the app title. This is not easy, and is even worse when the function needs user input a few times. This progress form is not a real progress form, since the bar movement is actually independent of the time the function takes to complete. But in most cases, that time is not known and the user just needs to know that the program is doing something and he/she needs to wait. I've been developing apps for my company for a few years, but I never went to school to learn programming, so you'll have to forgive me if I am not using the right terms and descriptions in this article. For this project, I implemented the progress bar using a GIF image instead of the progress bar class because it looks nicer. It shouldn't be hard to change it to a regular progress bar if needed.



Some cases where this can be very useful:

  • You just finished a big program and your boss tells you that in any place your app takes a few hundred milliseconds you have to show a progress bar because users will be confused if you don't show a progress bar.
  • A function is taking longer than you thought when you designed it.
  • To make your app fancier.
  • You woke up one morning loving progress bars.

Using the code

I included a library that includes everything to show and close the progress form, so just add the reference to the DLL or library project and call the Show() function to show and the Close() function to close it.

'Show form
progressForm.processThread.Show("Hello Universe...")
'Close form

Thread to open the form

When you show the progress form and you need input from the user or you open an external app while showing the progress form, the app loses focus after the progress form is closed. That is a weird but normal behavior when you open forms in another thread, so to fix that (and to avoid cross-thread problems), I added a timer that closes the form from its own thread and I use the ShowWindow() and SetForegroundWindow() functions from User32.dll to ensure the app gets its focus back after the progress form is closed.

Public Class processThread
    Shared messages As New List(Of String)
    Shared t As New List(Of Threading.Thread)
    Shared f As New List(Of frmProcess)

    Public Sub New()

    End Sub

    Public Shared Sub Show(ByVal message As String)
            f.Add(New frmProcess)
            AddHandler f.Last.Disposed, AddressOf formDisposed
            t.Add(New Threading.Thread(AddressOf showForm))

        Catch ex As Exception

        End Try

    End Sub

    <Runtime.InteropServices.DllImport("User32.dll")> _
    Private Shared Function SetForegroundWindow(ByVal hWnd As IntPtr) As IntPtr
    End Function
    <Runtime.InteropServices.DllImport("User32.dll")> _
    Private Shared Function ShowWindow(ByVal hWnd As IntPtr, _
            ByVal nCmdShow As Integer) As IntPtr
    End Function

    Private Shared Sub formDisposed()
            Dim procs() As Process = _
            If procs.Length = 1 Then
                ' the previously running instance will be at either index 0 or 1
                Dim index As Integer
                If CInt(procs(0).MainWindowHandle) <> 0 Then
                    index = 0
                    index = 1
                End If


                ShowWindow(procs(index).MainWindowHandle, 8) '8=SW_SHOWNA
            End If
        Catch ex As Exception

        End Try

    End Sub

    Public Shared Sub Close()
            If f.Count > 0 Then
                f.Last.TIMERON = False
                f.RemoveAt(f.Count - 1)
            End If
        Catch ex As Exception

        End Try

    End Sub

    Private Shared Sub showForm(ByVal message As String)
            If message IsNot Nothing AndAlso f.Count > 0 Then
            End If
        Catch ex As Exception

        End Try

    End Sub
End Class

Here is the progress form:

Imports System.Windows.Forms

Public Class frmProcess
    Inherits System.Windows.Forms.Form
    Public MESSAGE As String
    Public TIMERON As Boolean = False

    Private Sub frmProcess_FormClosing(ByVal sender As Object, _
            ByVal e As System.Windows.Forms.FormClosingEventArgs) _
            Handles Me.FormClosing
        Me.Timer1.Enabled = False
    End Sub
    Public Sub CloseIt()
    End Sub
    Public Overloads Sub ShowDialog(ByVal Mensaje As String)
        CheckForIllegalCrossThreadCalls = False
            TIMERON = True
            Me.Timer1.Enabled = True
            MESSAGE = Mensaje
            Me.lblMensaje.Text = Mensaje
        End Try
    End Sub

    Public Sub stopForm()
        TIMERON = False
    End Sub

    Private Sub frmProcess_Load(ByVal sender As System.Object, _
                ByVal e As System.EventArgs) Handles MyBase.Load

    End Sub

    Private Sub Timer1_Tick(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles Timer1.Tick
            If TIMERON = False Then
                Me.Timer1.Enabled = False
                Me.lblMensaje.Text = MESSAGE
            End If
        Catch ex As Exception

        End Try

    End Sub
End Class

Points of interest

This is not perfect, but it saved me a lot of time and works for almost every case in my apps. If the function where you need the progress bar is very complex (user inputs, external apps, multiple simultaneous progress bars), another approach might be better, but this probably will work.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Software Developer (Senior)
United States United States
No Biography provided

Comments and Discussions

PraiseGreat Job! Pin
Bill Tarlton10-Dec-20 6:04
MemberBill Tarlton10-Dec-20 6:04 
Generalgreat work Pin
sunny_0071-May-14 2:05
Membersunny_0071-May-14 2:05 
QuestionFlexible for my application... Pin
Sahayapraveen1-Apr-14 0:00
MemberSahayapraveen1-Apr-14 0:00 
QuestionGood control Pin
AlexiAnna15-Sep-12 21:20
MemberAlexiAnna15-Sep-12 21:20 
QuestionNice job Pin
thavaraj20-Apr-11 2:37
Memberthavaraj20-Apr-11 2:37 
GeneralThanks but Pin
scosta_FST30-Mar-11 3:39
Memberscosta_FST30-Mar-11 3:39 
Thank you for sharing your code.
Only a question: you dont solve the "Not Responding" problem, or I'm wrong?
GeneralRe: Thanks but Pin
andreslassalle1-Apr-11 7:19
Memberandreslassalle1-Apr-11 7:19 
GeneralGreat Job! Pin
Cebocadence29-Mar-11 7:29
MemberCebocadence29-Mar-11 7:29 
QuestionWhat about the ProgressBar.Style.Marquee? Pin
Olivier Levrey28-Mar-11 23:39
MemberOlivier Levrey28-Mar-11 23:39 
AnswerRe: What about the ProgressBar.Style.Marquee? Pin
andreslassalle1-Apr-11 7:21
Memberandreslassalle1-Apr-11 7:21 
GeneralRe: What about the ProgressBar.Style.Marquee? Pin
Olivier Levrey3-Apr-11 4:27
MemberOlivier Levrey3-Apr-11 4:27 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.