Comparing the Safety of Thread Calls in Visual Basic to Background Worker Calls

There are times where you first have to compare different ways of achieving the same goal. Using threads or backgroundworkers basically do the same thing, but, only if you use them right. Today, I will show compare unsafe threading calls to backgroundworker calls.

Threads

If you have never heard the term “Threads” before, let me explain. Any application makes use of threads to either show you information or a screen or to allow for long running tasks to complete. Now, threads are tricky and data is tricky. Sometimes, you will encounter a situation that may possibly freeze your application due to a long running task. So, instead of slamming all the code into one form, you have several threads. Each thread can run independently without affecting any other threads or user process.

Here is more information regarding threads.

BackgroundWorker

A BackgroundWorker object allows you to run an operation on a separate, dedicated thread. Similar to threads, time-consuming operations like downloads and database transactions that can cause your user interface to hang can be properly managed by running in a separate thread.

Here is more information on the BackgroundWorker class.

Let’s Do a Project

The aim of this project is to show you how to use threads to make unsafe calls, safe calls, and use a backgroundworker to make safe calls.

Create a new Visual Basic Windows Forms project and add another form to your project. Both forms should look like Figures 1 and 2:

Safety1
Figure 1: Form 1

Safety2
Figure 2: Form 2

Code

All of the code will take place on Form 1. Add the following namespaces:

Imports System
Imports System.ComponentModel
Imports System.Threading
Imports System.Windows.Forms

These namespaces allow us to work with threads.

Add the following variable objects to your code:

   Delegate Sub SetTextCallback(ByVal [text] As String)

   Private demoThread As Thread = Nothing

   Private WithEvents backgroundWorker1 As BackgroundWorker

   Private textBox1 As TextBox
   Private WithEvents setTextUnsafeBtn As Button
   Private WithEvents setTextSafeBtn As Button
   Private WithEvents setTextBackgroundWorkerBtn As Button

Here, I created a delegate procedure named SetTextCallBack, which we will later use with a thread operation. I created a thread object named demoThread as well as a Backgroundworker object. The following objects are simply controls that you will access through code.

For more information on Delegates, read here.

Using Threads

Add the following code:

   Private Sub setTextUnsafeBtn_Click( _
   ByVal sender As Object, _
   ByVal e As EventArgs) Handles setTextUnsafeBtn.Click

      Me.demoThread = New Thread( _
      New ThreadStart(AddressOf Me.ThreadProcUnsafe))

      Me.demoThread.Start()
   End Sub

   Private Sub ThreadProcUnsafe()
      Me.textBox1.Text = "This text was set unsafely."
   End Sub

This is an unsafe way to use threads to do tasks. Why? Before I get into details, add the following safe way to use a thread.

   Private Sub setTextSafeBtn_Click( _
   ByVal sender As Object, _
   ByVal e As EventArgs) Handles setTextSafeBtn.Click

      Me.demoThread = New Thread( _
      New ThreadStart(AddressOf Me.ThreadProcSafe))

      Me.demoThread.Start()
   End Sub

   Private Sub ThreadProcSafe()
      Me.SetText("This text was set safely.")
   End Sub

If you look closely, you may be able to see the subtle, yet big, difference between the preceding two code segments.

Backgroundworker

Add the following code for the Backgroundworker:

   Private Sub SetText(ByVal [text] As String

      If Me.textBox1.InvokeRequired Then
         Dim d As New SetTextCallback(AddressOf SetText)
         Me.Invoke(d, New Object() {[text]})
      Else
         Me.textBox1.Text = [text]
      End If
   End Sub

   Private Sub setTextBackgroundWorkerBtn_Click( _
   ByVal sender As Object, _
   ByVal e As EventArgs) Handles setTextBackgroundWorkerBtn.Click
      Me.backgroundWorker1.RunWorkerAsync()
   End Sub

   Private Sub backgroundWorker1_RunWorkerCompleted( _
   ByVal sender As Object, _
   ByVal e As RunWorkerCompletedEventArgs) _
   Handles backgroundWorker1.RunWorkerCompleted
      Me.textBox1.Text = _
      "This text was set safely by BackgroundWorker."
   End Sub

Here, I have made use of the BackgroundWorker to set the text property of a textbox. Because the BackgroundWorker inherently spawns a separate thread, all the work will not get done on one thread only.

Conclusion

Using threads properly or using BackgroundWorker objects can speed up your application’s performance and reduce freezing of applications. Although the above coding samples were used on simple operations, the long term effects in your application’s speed will be tangible.

Hannes DuPreez
Hannes DuPreez
Ockert J. du Preez is a passionate coder and always willing to learn. He has written hundreds of developer articles over the years detailing his programming quests and adventures. He has written the following books: Visual Studio 2019 In-Depth (BpB Publications) JavaScript for Gurus (BpB Publications) He was the Technical Editor for Professional C++, 5th Edition (Wiley) He was a Microsoft Most Valuable Professional for .NET (2008–2017).

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read