CONTENT
 PRODUCTS
 ARTICLES
 DOWNLOAD
 SOURCE CODE
 BOOK
 ABOUT
 HOME

MVP

ADS




Develop More Responsive Applications Using Multiple Threads
You can design your application to perform multiple tasks simultaneously and make it appear faster and more responsive. The Pocket PC operating system, Microsoft Windows CE, can handle multiple so called threads at the same time and the .NET Compact Framework makes it easier than ever to develop multithreaded applications. Read on to learn how to make those threads work for you!

The purpose of this article is to illustrate one of several purposes of multithreading using .NET Compact Framework and Visual Basic .NET.

You can download this article's sample source code!
Threads Anyplace
Threads Anyplace

Most Users Already Use Threads
As you already may know, your Pocket PC can load, run and maintain several applications simultaneously. For example, you can download email, listen to music using the Windows Media Player while you at the same time check the last monthly report in Pocket Excel. This multitasking feature of Windows CE works also within one and the same application. Some examples of creating multiple threads within one application include:

 Call more than one XML Web Service and handle the responses asynchronously
 Control and illustrate several game characters position and movements at the same time
 Allow asynchronous I/O operations
 Populate application user interface while allowing user to continue input data

There are many more valuable scenarios where multithreading adds capabilities and responsiveness. This article will provide a more detailed focus on how to add responsiveness to your user interface dealings.

No Magic Silver Bullet
The Pocket PC has only one processor. The processor can only execute one instruction at the time. To provide multitasking between different threads, Windows CE allocates a time slice to one thread at the time. The executing thread is put on hold when its time slice is up, and the next thread starts. A time slice is short, so on the surface it looks as if threads execute at the same time. However, creating a new thread for every application procedure is a seriously bad idea:

 Managing multiple threads is quite costly for the operating system in terms of maintaining thread state (context) for all threads
 Switching between threads is time consuming
 Code can become more error prone, and a real pain to debug, as multiple threads can be developed to use and manipulate the same objects

Threading is, as you can see, not the Performance Magic Silver Bullet you would perhaps want it to be.

The Key: System.Threading
The .NET Compact Framework provides the key to the operating system threading capabilities through the System.Threading classes. Some classes, methods, properties, and events are missing from the full .NET Framework, which is to be expected. The fundamental feature set is, however, intact and exposes the key functionality necessary to commence multithreaded application development. The following types are available:

 AutoResetEvent
 Interlocked
 ManualResetEvent
 Monitor
 Mutex
 Thread
 ThreadPool
 ThreadStart
 ThreadStateException
 Timeout
 Timer
 TimerCallback
 WaitCallback
 WaitHandle

The main type is the Thread type, which implements the following interface:

Instance Constructor: (ThreadStart start)

Properties:
 CurrentThread Thread CurrentThread

Methods:
 AllocateDataSlot ( )
 AllocateNamedDataSlot ( String name )
 FreeNamedDataSlot ( String name )
 GetData ( LocalDataStoreSlot slot )
 GetNamedDataSlot ( String name )
 SetData ( LocalDataStoreSlot slot, Object data )
 Sleep ( Int32 millisecondsTimeout )
 Start ( )

Let's take a look at how it all works!

Threads Anyplace Sample
This article's sample project, "Threads Anyplace" is intended to show how to use multithreading to create a more responsive application. Most applications have to deal with populating user interface with data as well as deal with user input. User interface code often executes as forms are loaded, filling list boxes and other controls with data. When this process has finished executing, and only then, the user can continue working with the application and start entering data. The time it takes to populate the user interface is the time the user has to wait.

"Threads Anyplace" implements a user interface class that is responsible for filling controls with data. The application uses three controls: a list box, a drop down combo box, and a text box. While the list box and combo box is populated on separate threads, the user can continue to enter data in the text box on the application’s main thread. Starting a separate thread is quite straightforward and is done when the Thread type is instantiated using the following syntax:
  Thread(AddressOf method)
The reason why I have chosen to implement the user interface class is primarily to show how to pass data to a new thread. You can not pass data to the new thread when the thread is constructed. If you need to pass data to a new thread that it needs to execute, you need to put the method referenced in the AddressOf parameter, in a separate class. When the separate class is instantiated before the thread you can pass the data by setting property values. When all data is passed to the class, you can then instantiate the thread with the appropriate method call. The sample application uses one form:

Threads Anyplace sample
Threads Anyplace Sample

To show how much more responsive the application becomes when using multiple threads; I have implemented the same user interface population on one and the same thread. Once again I hope to win first prize in any user interface competition!

Code Walkthrough
The following code executes when the user taps the Populate-button:
Private Sub btnPopulate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnPopulate.Click
  ' Variables
  Dim UI As New UserInterface

  ' Set User Interface properties
  UI.ComboBox = Me.cmbProducts
  UI.ListBox = Me.lstSuppliers

  ' Turn on wait cursor
  Cursor.Current = Cursors.WaitCursor

  Try
    If radMainThread.Checked = True Then
      UI.PopulateCombo()
      UI.PopulateListbox()
    Else
      ' Create thread to populate the combobox
      trd = New Thread(AddressOf UI.PopulateCombo)
      trd.Start()
      ' Create thread to populate the listbox
      trd = New Thread(AddressOf UI.PopulateListbox)
      trd.Start()
    End If
  Catch ex As Exception
    MsgBox(ex.Message)
  Finally
    ' Turn off wait cursor
    Cursor.Current = Cursors.Default
  End Try
End Sub
In this sample, I pass the list box control and combo box control to the user interface class by setting the class properties ComboBox and ListBox. My plan is to implement a generic user interface helper class which could prove useful from many perspectives. One obvious benefit to implement a user interface helper class is that it becomes a relevant place to put the code solving the ID/Description pairing, which is an issue every time a list box or combo box is populated.

The user interface class looks like this:
Public Class UserInterface
  Private mComboBox As ComboBox
  Private mListBox As ListBox

  Public Property ComboBox() As ComboBox
    Get
      Return mComboBox
    End Get
    Set(ByVal Value As ComboBox)
      mComboBox = Value
    End Set
  End Property

  Public Property ListBox() As ListBox
    Get
      Return mListBox
    End Get
    Set(ByVal Value As ListBox)
      mListBox = Value
    End Set
  End Property

  Public Sub PopulateCombo()
    ' Variables
    Dim cmd As New SqlCeCommand("SELECT ProductName FROM Products", frmThreadsAnyplace.cn)
    Dim dr As SqlCeDataReader

    mComboBox.Items.Clear()

    Try
      ' Execute the reader
      dr = cmd.ExecuteReader()
      ' Populate the combo box
      While dr.Read()
        mComboBox.Items.Add(dr("ProductName"))
      End While
      mComboBox.SelectedIndex = 0
    Catch ex As SqlCeException
      MsgBox(ex.Message)
    Finally
    End Try
  End Sub

  Public Sub PopulateListbox()
    ' Variables
    Dim cmd As New SqlCeCommand("SELECT CompanyName FROM Suppliers", frmThreadsAnyplace.cn)
    Dim dr As SqlCeDataReader

    mListBox.Items.Clear()

    Try
      ' Execute the reader
      dr = cmd.ExecuteReader()
      ' Populate the combo box
      While dr.Read()
        mListBox.Items.Add(dr("CompanyName"))
      End While
      mListBox.SelectedIndex = 0
    Catch ex As SqlCeException
      MsgBox(ex.Message)
    Finally
    End Try
  End Sub
End Class
There are certainly more steps necessary to take before this class can be used generically; abstracting SQL-statements being one of them. Go for it!

Conclusion
I hope this article will help you getting started building more responsive multithreaded applications. If you manage and deal the risks involved appropriately you can start leveraging the operating system's threading capabilities, replacing wait cursors with more power.

Any comments?

©2001-2009 Christian Forsberg & Andreas Sjöström