Virtual Developer Workshop: Containerized Development with Docker
Welcome to my article! Today I will be demonstrating how easy it is to work with threads in your VB.NET application.
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.
To demonstrate how simple threads are, I have decided to create a little app for that purpose. Our app will spawn threads from another thread. Now, let us start with the practical part.
Not much of a design as all the controls needed will be added during runtime via threads. Open Visual Studio 2012 and create a new Windows Forms VB.NET application. Once done, add a second form to your project. Add a Timer control to Form1.
Add the following Imports statement above your form declaration:
Imports System.Threading 'Imports Threading Namespace
This enables us to work with threads.
Declare the following modular variables:
Dim F2 As New frmThread2 'Create New Form 2 Object Dim strText As String = "Thread Is Running!" 'Text To Display Dim lbList As New ListBox 'Create New ListBox, Used By Form 2
Here, I created a form object to represent Form2. I created a string object to be used later, as well as a ListBox object. This object will later be added to Form 2, during a thread's execution.
Create a Form_Load event procedure that looks like the following code segment:
Private Sub frmThread1_Load(sender As Object, e As EventArgs) Handles Me.Load 'Create Thread, and Specify Delegate Dim tThread1 As New Thread(AddressOf ThreadProcedure) 'Start A Thread tThread1.Start() 'Show Form 2 F2.Show() F2.TopMost = True End Sub
The first line of code creates a new thread and tells the thread what to do. This is done via the AddressOf statement. AddressOf specifies which procedure to run. In this case the procedure to run is ThreadProcedure, which we will add shortly. The next couple of lines instantiates the Form 2 object and shows it in front of Form1.
Add the ThreadProcedure code:
'What Thread 1 Must Do Private Sub ThreadProcedure() 'Specify Properties For ListBox lbList.Location = New Point(0, 0) lbList.Width = 300 lbList.Height = 300 lbList.Items.Add(strText) 'Add Text 'Call Delegate To Add ListBox To A Different Thread AddControlToForm(lbList) End Sub
Not much happening here, as this is only an introduction to threading. What I did here was to simply set some properties of the ListBox, then most importantly, call the AddControlToForm sub procedure - we will add this one momentarily.
Now, we sit with a problem. If you are very new to threads you may not know what the problem is. The problem is: because we are making use of a separate thread to add controls to a form, the program will complain. Why? because we need to authorize our thread to communicate with the application's thread in order to add the control to the form.
This is why we need to add a Delegate to do this work for us. If you do not know what a delegate is, see Delegates and VB.NET. This delegate will eventually add the ListBox to the second form from the thread named Thread1. Add the delegate now:
'Delegate Private Delegate Sub AddListBox(ByVal ctrToAdd As Control)
Now, add the AddControlToForm procedure:
Private Sub AddControlToForm(ByVal ctrl As Control) 'InvokeRequired Informs Us If We Are In Correct Thread If Me.InvokeRequired Then 'Not 'Create Another Delegate Dim TempDelegate As New AddListBox(AddressOf AddControlToForm) 'Store Parameters - OPTIONAL Dim parameters(0) As Object parameters(0) = ctrl 'Invoke TempDelegate Me.Invoke(TempDelegate, parameters) Else 'Yes F2.Controls.Add(ctrl) End If End Sub
I first determine which thread we are in, then based on that, added the ListBox to Form 2.
Add the last event procedure. This is for the Timer's Tick event:
Private Sub tmrThread_Tick(sender As Object, e As EventArgs) Handles tmrThread.Tick ThreadProcedure() 'Run Separate Thread End Sub
The Timer will call ThreadProcedure that creates the thread, and call its associated delegates.
See, I told you Threads were not so bad! I hope you enjoyed this very short (to my standards) article. Stick around for more introductory articles coming soon!