Background Processing in VB

How do you code background processing in VB5?

I am designing an app where part of the app runs some serious mathematical code and takes hours to run.  I would like to place this processing in the background enabling the user to continue using the app.  I tried using an ActiveX EXE but am unable to return control back to the main app.

Can you please provide some example code?
Who is Participating?
Start a timer in your ActiveX server. This timer can be on a invisible form.
So the activeX server has a method DoSomething. DoSomething enables the timer. On the timer event you can do your stuff.
The server can launch an event when it is finished.

   Dim withevents myServer as MyActiveXServer
sub form_load
   set   myServer = new MyActiveServer
end sub

sub command1_click
end sub

sub myServer_Finished
   msgbox "Finished"
end sub

event Finished

public sub DoSomething
   timer1.enabled = true  
end sub

sub timer1_click
  timer1.enabled = false
  <Do your stuff>
  raiseevent Finished
end sub

McIx is better at this than I am, but this is how I understand how it works.  You create an object that runs on the server asyncronously.  You create this object where it has an event.  When it is done it raises an event.  The program that called it 'Dim'ed it with events.  So, when the object raises the event, the processing object can process the fact that it is done.  MTS or 'Remote Automation Manager' help you manage remote executing events.

Good Luck,
Assuming he has a server?
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

You could launch some threads to do the work.

Waty is right for the threads,
but what I found quite effective is the good old shell
Shell is multithreaded, therefore pass the parameters
to your exe when you shell it.

Downside, what was 1 app, now becomes 2.
A shells B, B never works alone.

But in your case,
it is not that bad, A will contine to run letting the user
continue while B is calculating.

With VB5 it is easy to your own ActiveX objects. These run in a separate thread from the main program. I personally think that the are usually the easiest way to get VB to do multithreading. If you create one that does the lengthy process then you will be able to leave it running. You could even have an event that the object can drive to tell you it has finished. I think this is probably what mkmccreary was referring to. Let me know if you need any help.
sadkatAuthor Commented:
The Shell function is OK, but it does not allow me to pass variables and other infromation to the calculation app.  The variables passed come from the main app and will be different each time the calculation app is called.

sadkatAuthor Commented:
Thank's for your help so far.  The code is working OK.


In the ActiveX server I want to minimize a form (already coded) and show the progress of the calc (% complete like an internet download) in the form's caption.

It seems once the focus is given back to the client I cannot update the ActiveX server form's caption.

Any ideas or code.  Thanks for your help!!
sadkatAuthor Commented:
I'm able to set multiple calls of the calc app.  BUT the calls are working sequentially.  Call 2 must finish before call 1 finishes etc.


In Client :-

Private Sub mnuRun_Click()
  Dim myServer As TestActiveX.TestDCG
  Set myServer = New TestActiveX.TestDCG
End Sub

In Server :-

In Class Module:

Dim frm As New TestForm

Public Sub DoSomething()
  frm.Show vbModeless
  frm.WindowState = vbMinimized
  frm.Timer1.Enabled = True
End Sub

In Form:
Private Sub Timer1_Timer()
  Timer1.Enabled = False
  Unload Me
End Sub

Private Sub DoSims()
  Dim i As Long
  For i = 1 To 10000
    Caption = i
  Next i
End Sub

The server still has one threat and can only handle one call at the time.

So you cannot start the next DoSomething until the previous one is finished.

Here are some things to think about.
1) Dim myServer As TestActiveX.TestDCG is declared local.
That means that it is immediatelly destroyed after you start DoSomething. Your DoSims is never executed. Make this a global variable.

2) Make sure that the timer is enabled = false and interval = 50
Otherwise your timer is already started before you give the command or is not started at all.

3) Here is a more elaborate example.
---- CLIENT FORM ----
Option Explicit
Dim WithEvents m_myserver As ActiveXExe ' Global declaration of the exe

Private Sub Command1_Click()
    On Error GoTo leave
    m_myserver.DoSomething   'Start exe, second call while busy will raise error
    Select Case Err.Number
        Case 0
        Case -1
            MsgBox "The server is busy, please wait"
        Case Else
            MsgBox Err.Description
    End Select
End Sub

Private Sub Form_Load()
    Set m_myserver = New ActiveXExe 'Create the server
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Set m_myserver = Nothing 'Destroy the server
End Sub

Private Sub m_myserver_Finished(ByVal OK As Boolean)
    MsgBox IIf(OK, "Finished", "Aborted at " & m_myserver.progress) 'Notify user about server state
End Sub

Option Explicit

Dim WithEvents frm As Form
Dim WithEvents frmtimer As Timer
Dim fBusy As Boolean
Dim m_prg As Long

Public Event Finished(ByVal OK As Boolean)

Public Property Get Progress() As Integer
    Progress = m_prg
End Property

Public Sub DoSomething()
    If (fBusy = True) Then
        Err.Raise -1, , "Exe is Busy"
    End If
    fBusy = True
    frm.Show vbModeless
    frm.WindowState = vbMinimized
    frmtimer.Enabled = True
End Sub

Private Sub Class_Initialize()
    m_prg = 0
    Set frm = New Form1
    Set frmtimer = frm.Timer1
End Sub

Private Sub Class_Terminate()
    Unload frm
    Set frmtimer = Nothing
    Set frm = Nothing
End Sub

Private Sub frm_Unload(Cancel As Integer)
    RaiseEvent Finished(Not fBusy) 'raise event
    If (fBusy) Then fBusy = False  ' abort
    m_prg = 0
End Sub

Private Sub frmtimer_Timer()
    frmtimer.Enabled = False
    Unload frm
End Sub

Private Sub DoSims()
    For m_prg = 1 To 10000
        If Not fBusy Then Exit Sub 'aborted
        frm.Label1.Caption = m_prg
    Next m_prg
    fBusy = False
    m_prg = 0
End Sub

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.