Asynchronous Calling, New and Improved
You've seen how to asynchronously invoke an object's method using a delegate and also how to retrieve the results, whenever they may be available, from a callback routine. You have accomplished this from a client application. If you'd like, you can distribute the FileFunctions object as a component to anyone you like, but it would be up to them to write the plumbing code needed to make asynchronous calls to any of its methods.
Now you're going to learn how to encapsulate most of this into the business object itself. This allows you to distribute the business object as a component and provides the methods needed to invoke the MoveFiles
routine, or any other for that matter, asynchronously. You add all this built-in functionality using the standard naming conventions mentioned earlier, which are already in use throughout the .NET Framework. Yes, you guessed it; you will be adding two new methods to the FileFunctions object: BeginMoveFiles
. The main advantage of this naming convention is that it is, for the most part, self-explanatory. When you distribute your business object, the reasons for having MoveFiles
, and EndMoveFiles
methods will be apparent to anyone who has worked with asynchronous delegates in the past.
So let's get started. The first thing you need to do is declare the delegate as in the previous examples:
In VB .NET
public delegate bool MoveFilesDelegate(
string origin, string destination);
Public Delegate Function MoveFilesDelegate( _
ByVal origin As String, _
ByVal destination As String) _
This statement is identical to before; I show it again here because it may be located differently this time. You are assuming that the FileFunctions class may be in a stand-alone component so that it may be distributed later. The delegate declaration must now be accessible to this class without relying on an outside component, so you need to make sure that it is declared somewhere in the component in which this class resides. Keep in mind, a delegate declaration is still made outside the scope of a class. The code for the complete component is in Listing 1
(C#) and Listing 2
The next thing to do is add a BeginMoveFiles
method to the class. This method has a return type of IAsyncResult, and conforms to the signature you saw in the BeginInvoke
method previously. The signature was comprised of the two arguments MoveFiles
receives, the AsyncCallback routine and the AsyncState object. Take a look at the method in its entirety and then I'll dissect it piece by piece. Whether you remember the method of asynchronous calling from this article or were already familiar with asynchronous delegate use, the code in this method will make a lot of sense to you.
In VB .NET
public IAsyncResult BeginMoveFiles(
MoveFilesDelegate o_MyDelegate =
Public Function BeginMoveFiles( _
ByVal sourceFolder As String, _
ByVal destinationFolder As String, _
ByVal callback As AsyncCallback, _
ByVal asyncState As Object) _
Dim o_MyDelegate As MoveFilesDelegate = _
New MoveFilesDelegate( _
Return o_MyDelegate.BeginInvoke( _
sourceFolder, destinationFolder, _
Of course, it looks familiar. Look at the first line of code (after the method declaration). The delegate object is instantiated just like before but with one difference. In the first example, you instantiated FileFunctions and then wired the MoveFiles
method into the delegate declaration. The MoveFiles
method is not in an instantiated object; instead the MoveFiles
method is within this class itself.
The second line invokes the delegate with the ever-popular asynchronous launcher method, BeginInvoke
. As before, the signature includes the MoveFiles
arguments, the callback routine, and the generic AsyncState object. Note that the variable used to identify the callback came to this function as an argument. Unlike the first example, you do not have to declare an AsyncCallback delegate instance for this routine, because the variable already comes into this method as one. You will see how when I demonstrate the client application's code. The entire instance of the BeginInvoke
method is returned to the caller as an implementation of the IAsyncResult interface.