Introduction
This article has come out more of my curiosity and penchant towards asynchronous processing, its basics and features. In this article, I shall try to cover these areas.
- Basics & the need for asynchronous processing
- Differences between synchronous and asynchronous processing
- How-to implement asynchronous processing in VB6 and in .NET, and in turn figure out how efficient it is in .NET.
- Conclusion
Consider this scenario � I would like to transfer a junk of files to some location as part of my application. Visual Basic offers APIs, file system object and many more, through which I can accomplish this. Say, I can just write CopyFile <SourceFile> <Destination>
and loop it to transfer files. Yes, it would certainly work and is fine when the amount of the size of the files you transfer is less. When you try this with a huge file or more number of files, you will notice that the whole process is blocked when file transfer is in progress. You won�t be able to do anything else until the transfer is complete. Wouldn�t it be nice if the transfer happens at the background and you would be able to do any other operation (say any UI functions or even cancel the transfer operation) while the transfer is happening. This exactly is where the need arises for asynchronous processing.
The above said method is synchronous, where the main application thread is utilized for this transfer and until the operation is complete, this thread is not released for any other UI operations. (Even if you wish to cancel the transfer of files for some reason, you won�t be able to do).
And accomplishing this background processing is what we are focusing on � asynchronous processing, where the operation is carried out in a separate thread than that of the calling thread, leaving the main thread to do any other operation. This gives the user the control to do anything when processing (as transferring files). And the child thread created can callback the main thread to intimate when the transfer is complete or when an error occurs, on which the application can act accordingly.
Implementation
If you have evolved with the versions of VB, then you would not deny the fact that implementing asynchronous processing is not so straightforward. Versions later than VB 5 though provided the possibility of running VB applications multithreaded by using ActiveX EXEs, a counterpart to ActiveX DLLs. ActiveX DLLs are in-process routines which run in the same process as the calling application and hence work synchronously. In contrary, ActiveX EXEs are out-of-process routines, which run in a separate process and hence work asynchronously. (You can get an insight of in-process and out-of-process components and its features if you see any COM article).
Here, I shall try to explain to you the implementation of asynchronous processing dealt with VB and with VB.NET. I shall in turn take a small example, where a routine unnecessarily makes some delay (necessarily to explain the scenario here, though) through a sleep event.
With VB
Asynchronous components in VB, as we saw will be implemented with ActiveX EXE. (A project of ActiveX EXE type has to be created to develop an ActiveX EXE component). The basic steps involved in creating this would include:
- Including the procedure into an ActiveX EXE, and let them be private
- Include a wrapper method to call the private procedure, which needs to be run asynchronous. Well, the wrapper just doesn�t do this alone (which makes no difference between this and the original), but it also incorporates a timer that it enables. When the timer event fires, the original method is called.
Note: This sample that I�ve sketched is based on the example, which is available in vbaccelerator.com, which I�ve found by far as the best way to implement the ActiveX EXEs. I�ve tried to explain this piece of code in detail.
The idea of having a timer doesn�t mean that we are forced to use a form that can hold the timer. We can as well have a class, which provides the functionality of a timer. You can find this here and at many other sites, though I suggest the one mentioned.
Also, instead of directly referencing the object instance in the module, an error-free interface, Runnable
, a type library that you will find in the MSDN�s CodeFlow sample is being used.
The class module will look like this (I�ve excluded the API�s and other declarations for readability of the core function)
cAsync.cls
Public Sub Start()
If Not m_bRunning Then
m_bRunning = True
mStart.Start Me
Else
Err.Raise 32540, App.EXEName & ".cAsync", "Already running."
End If
End Sub
Private Sub Runnable_Start()
Dim i As Long
Dim bCancel As Boolean
Do
SleepAPI 100
i = i + 1
RaiseEvent Status(i, bCancel)
Loop While (i < m_lInterval) And Not bCancel
If i = m_lInterval Then
RaiseEvent Complete
Else
RaiseEvent Cancelled
End If
m_bRunning = False
End Sub
mStart.bas
(Callback interface is used, which in turn needs the address of the function, and this forces us to use a module which provides this option).
Private Sub TimerProc(ByVal lHwnd As Long, ByVal lMsg As Long, _
ByVal lTimerID As Long, ByVal lTime As Long)
Dim this As Runnable
With m_colRunnables
Do While .Count > 0
Set this = .Item(1)
.Remove 1
this.Start
CoLockObjectExternal this, 0, 1
Loop
End With
KillTimer 0, lTimerID
m_lTimerID = 0
End Sub
Public Sub Start(this As Runnable)
CoLockObjectExternal this, 1, 1
If m_colRunnables Is Nothing Then
Set m_colRunnables = New Collection
End If
m_colRunnables.Add this
If Not m_lTimerID Then
m_lTimerID = SetTimer(0, 0, 1, AddressOf TimerProc)
End If
End Sub
This is a very basic sample of how to implement ActiveX EXE in the Visual Basic 6 environment.
This is the first part of this article that explains the basics of asynchronous processing and how it is implemented in VB6. I shall, in the next part of this article, give a solution in VB.NET, and explain how different it is and how sophisticated it is to develop the same.