Home
Search
 
What's New
Index
Books
Links
Q & A
Newsletter
Banners
 
Feedback
Tip Jar
 
C# Helper...
 
XML RSS Feed
Follow VBHelper on Twitter
 
 
MSDN Visual Basic Community
 
 
 
 
 
TitleLet a long process run asynchronously without multithreading
Keywordslong process, multithreading, thread
CategoriesSoftware Engineering
 
This example shows how to build a FibonacciLibrary DLL. This DLL contains a public class FibonacciCalculator that performs a long calculation: it calculates Fibonacci numbers recursively. (There are much faster methods for calculating Fibonacci numbers but this one makes an easy example. See my book Ready-to-Run Visual Basic Algorithms for faster methods.)

The main program creates a FibonacciLibrary.CalculateFibonacci object and calls its public CalculateFibonacci subroutine to start the calculation. CalculateFibonacci stores a reference to the current CalculateFibonacci object in the variable g_FibonacciCalculator and saves its parameter in m_Parameter. It uses the SetTimer API function to create a timer that will wait for 1 millisecond and then returns. (You could use a hidden form with a Timer control on it instead of an API timer if you wanted.)

 
' Start calculating a Fibonacci number the slow,
' stupid way.
Public Sub CalculateFibonacci(ByVal i As Integer)
    ' Save a reference to ourself.
    Set g_FibonacciCalculator = Me

    ' Save the parameter.
    m_Parameter = i

    ' Start the timer.
    g_TimerId = SetTimer(0, 0, 1, _
        AddressOf FibonacciTimer)

    ' Return so the main program can do stuff.
End Sub
 
When the API timer fires, it calls the FibonacciTimer subroutine. This routine is in a BAS module within the FibonacciLibrary project. FibonacciTimer kills the timer so it doesn't execute again and then calls the saved FibonacciCalculator object's BeginFibonacciCalculation to begin the actual calculation.
 
' Start calculating the Fibonacci number.
Public Sub FibonacciTimer(hwnd As Long, msg As Long, _
    idTimer As Long, dwTime As Long)
    ' Stop the timer.
    KillTimer 0, g_TimerId

    ' Start the actual Fibonacci calculation.
    g_FibonacciCalculator.BeginFibonacciCalculation
End Sub
 
BeginFibonacciCalculation calls the Fibonacci function to calculate the Fibonacci number. It then raises the FibonacciDone event to give the main program the result.
 
' Start calculating a Fibonacci number the slow,
' stupid way.
Friend Sub BeginFibonacciCalculation()
Dim result As Double

    ' Perform the calculation.
    m_Iterations = 0
    result = Fibonacci(m_Parameter)

    ' Return the result.
    RaiseEvent FibonacciDone(result)
End Sub

' Recursively calculate the Fibonacci number.
Private Function Fibonacci(ByVal i As Double) As Double
    ' Every now and then, give the main program
    ' a chance to do something.
    m_Iterations = m_Iterations + 1
    If m_Iterations Mod 100 = 0 Then DoEvents

    ' Calculate the Fibonacci number.
    If i <= 1 Then
        Fibonacci = 1
    Else
        Fibonacci = Fibonacci(i - 1) + Fibonacci(i - 2)
    End If
End Function
 
The following code shows how the main program works. When the user clicks the Calculate button, its event handler clears any previous results, enables the Timer tmrWaiting, and invokes the FibonacciCalculator's CalculateFibonacci method.

When the tmrWaiting Timer fires, the program displays the number of ellapsed seconds.

When the FibonacciCalculator finishes, the FibonacciDone event handler displays the result and disables tmrWaiting.

 
Private WithEvents m_Calculator As _
    FibonacciLibrary.FibonacciCalculator

Private m_StartTime As Single

Private Sub cmdCalculate_Click()
    ' Clear the previous results.
    lblResult.Caption = ""
    lblTime.Caption = ""
    tmrWaiting.Enabled = True
    m_StartTime = Timer
    DoEvents

    ' Start calculating the Fibonacci number.
    m_Calculator.CalculateFibonacci CInt(txtNumber.Text)
End Sub

Private Sub tmrWaiting_Timer()
    lblTime.Caption = CInt(Timer - m_StartTime)
End Sub

Private Sub m_Calculator_FibonacciDone(ByVal result As _
    Double)
    ' Display the result.
    lblResult.Caption = result

    tmrWaiting.Enabled = False
End Sub
 
This example doesn't really provide much feedback. The main program simply displays the ellapsed time since the Fibonacci calculation started. Increasing the number by 1 roughly doubles the execution time to start with small values (25 or so) and slowly increase them until you see how the program runs on your computer.

Another method for providing feedback would be to give the FibonacciCalculator a public status routine so the main program could periodically ask it how far the calculation had gone. Perhaps a better technique would be to make the FibonacciCalculator periodically raise status events telling the main program how far it had gone in its calculation.

 
 
Copyright © 1997-2010 Rocky Mountain Computer Consulting, Inc.   All rights reserved.
  Updated