Hello All, 
     For Today's Tech Tip, we thought we would branch out from 
just showcasing the great built in features of our controls and show off some 
.NET functionality that can be applied to numerous scenarios involving many 
different controls and applications. 
					 
Multi-Threading 
The basic concept for multi-threading is to take the major processing away 
from the main application thread (to avoid the dreaded "Not Responding" message 
from windows), and also to be able to give proper feedback to users as tasks 
process and complete. 
A nice and easy way to reflect the current status of an operation is with, 
everyone's favorite control, the Progress Bar. The Progress Bar is universally 
understood, well if you are used to using computers at least :), and a very 
simple way to display the needed information.  The issue that arises when 
trying to use it, is that trying to perform your processing and updating the 
Progress Bar, will max out the current thread and bring the application to its 
knees.  This is where Multi-Threading comes in, because you can move ALL 
of the processing operations to new threads, and leave the main thread to refresh 
the Progress Bar with the progress as each thread reports back. 
  
We have have put together a small sample that shows using two threads for 
"processing" in addition to the main application thread. 
This sample uses the following controls, on a single form: 
2 
dbiMeter controls (used as Progress Bars) 
1 
dbiDial control (used to modify the increment of 1 dbiMeter) 
1 
dbiSlide control (used to modify the increment of 1 dbiMeter) 
4 standard button controls (used for starting and stopping the additional 
threads) 
2 Background Worker controls (these controls will handle the additional 
threads). 
  
Here is what the form looks like with all the controls: 
					
					  
And because they are non-visual controls, the 2 Background Workers will 
appear in the Designer Tray, below the form in the Visual Studio designer, like 
so: 
  
 
Now for the code: 
 
Here we initialize the form, and set the range of the dbiDial and dbiSlide 
controls.  In this example, these two controls can be used to change the 
value the dbiMeter controls will increment by (1-10). They are independent of 
each other and only affect 1 dbiMeter each. 
 
Private
Sub Form1_Load(ByVal 
sender As Object,
ByVal e As 
System.EventArgs) Handles
Me.Load 
        
'Set up the dbiDial and dbiSlide controls with a few 
parameters. 
        
'These controls will be used to adjust the increments 
of the dbiMeter controls. 
       
Me.DbiDial1.Maximum = 10 
        
Me.DbiDial1.Minimum = 1 
        
Me.DbiDial1.Value = 1 
        
Me.DbiSlide1.Maximum = 10 
        
Me.DbiSlide1.Minimum = 1 
        
Me.DbiSlide1.Value = 1 
        
Me.DbiSlide1.ShowDivisions = 0 
        
Me.DbiSlide1.ShowMax = 10 
        
Me.DbiSlide1.ShowMin = 1 
       
Me.ButtonStop1.Enabled =
False 
       
Me.ButtonStop2.Enabled =
False 
        'The 
background workers will be allowed to report their progress as well as be 
cancelled 
        
Me.BGW_DialMeter.WorkerReportsProgress 
= True 
       
Me.BGW_DialMeter.WorkerSupportsCancellation 
= True 
       
Me.BGW_SlideMeter.WorkerReportsProgress =
True 
       
Me.BGW_SlideMeter.WorkerSupportsCancellation 
= True 
    
End Sub 
And here is the code for the first group of controls (1 dbiMeter, 1 dbiDial, 
2 standard buttons, and 1 of the Background Workers): 
 
#Region
"dbiMeter 1, Horizontal" 
 
    
Private Sub 
ButtonStart1_Click(ByVal sender
As System.Object, ByVal 
e As System.EventArgs) 
Handles ButtonStart1.Click 
        
Me.ButtonStart1.Enabled =
False 
       
Me.ButtonStop1.Enabled =
True 
       
Me.BGW_DialMeter.RunWorkerAsync()
'Start the background worker to run its process 
    
End Sub 
    
Private Sub 
ButtonStop1_Click(ByVal sender
As System.Object, ByVal 
e As System.EventArgs) 
Handles ButtonStop1.Click 
        
Me.BGW_DialMeter.CancelAsync()
'Tell the background worker to finish its processing 
       
Me.ButtonStop1.Enabled =
False 
       
Me.ButtonStart1.Enabled =
True 
    
End Sub 
    
Private Sub 
BGW_DialMeter_DoWork(ByVal sender
As Object,
ByVal e As 
System.ComponentModel.DoWorkEventArgs) Handles 
BGW_DialMeter.DoWork 
        
'To simulate processing, we will use a Do While Loop, 
and issue a Sleep command 
 
        
'As long as the background worker hasn't been told to 
stop, the loop will continue 
       
Do While 
BGW_DialMeter.CancellationPending = False 
 
           
'Update the dbiMeter control's value, to 
represent the progress 
           
If Me.DbiMeter1.Value 
+ Me.DbiDial1.Value <= 100
Then 
               
BGW_DialMeter.ReportProgress(Me.DbiMeter1.Value 
+ Me.DbiDial1.Value) 
           
Else 
               
BGW_DialMeter.ReportProgress(0) 
           
End If 
           
System.Threading.Thread.Sleep(1000) 'Pause the 
thread for 1 second 
       
Loop 
    
End Sub 
    
Private Sub 
BGW_DialMeter_ProgressChanged(ByVal sender
As Object,
ByVal e As 
System.ComponentModel.ProgressChangedEventArgs) Handles 
BGW_DialMeter.ProgressChanged 
        
'The dbiMeter control is updated with the progress 
reported by the background worker 
       
Me.DbiMeter1.Value = e.ProgressPercentage 
    
End Sub 
 #End 
Region 
The other set of controls has an identical set of code: 
#Region
"dbiMeter 2, Vertical" 
    
Private Sub 
ButtonStart2_Click(ByVal sender
As System.Object, ByVal 
e As System.EventArgs) 
Handles ButtonStart2.Click 
        
Me.ButtonStart2.Enabled =
False 
       
Me.ButtonStop2.Enabled =
True 
       
Me.BGW_SlideMeter.RunWorkerAsync()
'Start the background worker to run its process 
    
End Sub 
    
Private Sub 
ButtonStop2_Click(ByVal sender
As System.Object, ByVal 
e As System.EventArgs) 
Handles ButtonStop2.Click 
        
Me.BGW_SlideMeter.CancelAsync()
'Tell the background worker to finish its processing 
       
Me.ButtonStop2.Enabled =
False 
       
Me.ButtonStart2.Enabled =
True 
    
End Sub 
    
Private Sub 
BGW_SlideMeter_DoWork(ByVal sender
As Object,
ByVal e As 
System.ComponentModel.DoWorkEventArgs) Handles 
BGW_SlideMeter.DoWork 
        
'To simulate processing, we will use a Do While Loop, 
and issue a Sleep command 
 
       
'As long as the background worker hasn't been 
told to stop, the loop will continue 
       
Do While 
BGW_SlideMeter.CancellationPending = False 
 
           
'Update the dbiMeter control's value, to 
represent the progress 
           
If Me.DbiMeter2.Value 
+ Me.DbiSlide1.Value <= 100
Then 
               
BGW_SlideMeter.ReportProgress(Me.DbiMeter2.Value 
+ Me.DbiSlide1.Value) 
           
Else 
               
BGW_SlideMeter.ReportProgress(0) 
           
End If 
 
           
System.Threading.Thread.Sleep(1000) 'Pause the 
thread for 1 second 
       
Loop 
    
End Sub 
    
Private Sub 
BGW_SlideMeter_ProgressChanged(ByVal sender
As Object,
ByVal e As 
System.ComponentModel.ProgressChangedEventArgs) Handles 
BGW_SlideMeter.ProgressChanged 
        
'The dbiMeter control is updated with the progress 
reported by the background worker 
       
Me.DbiMeter2.Value = e.ProgressPercentage 
    
End Sub 
 #End 
Region 
When each of the Start buttons is pressed, they give the command to their 
respective Background Worker to begin running asynchronously.  The 
Background Worker will then trigger its DoWork event.  It is from this 
event that all processing on the secondary thread processes (when the event 
finishes, the Background Workers thread will automatically stop). In the example 
posted, we simply used a Do While Loop and a Sleep command to simulate the event 
performing a process.  In reality, you can use these events to handle your 
data load, or an update process, or even a constant validation routine when 
working in a multi-user data environment. 
 
To stop either of the Background Workers, simply press one of the stop buttons.  
This will call the CancelAsync method on the respective worker thread, which 
will set it as CancellationPending = True, which will end the process inside the 
DoWork event (stopping the thread). 
If you would like a closer look at the sample, in either a working example or 
the source code, please see the following links: 
Run a Smart Client sample: 
Download a compiled version of the sample: 
Download the Visual Basic .NET Visual Studio 2008 source code: 
 
Take care and have a nice day! 
					  
					 |