KnowDotNet

Asynchronous Programming - Part II

by William Ryan

Recently, I've decided to start refining my skills with Asynchronous methods.  Paul Kimmel's Visual Basic .NET Power Coding has a tremendous discussion of Asnychronous programming and I really liked his example of Asynchronous File IO.  Here's a really cool Example.  We know that .NET keeps with specific naming conventions and usually you can tell something is asynchronous if it begins with "Begin"  So let's take a look at how to read a file Asynchronously:

Since we are going to refer to some variables from within our async method, we need two module level variables:

Private Stream As FileStream = Nothing
Private
Data() As Byte

Next, we're going to create a Subroutine that accepts a filename as a parameter.  We're going to open in up and start reading it asynchronously:

Private Sub BeginProcess(ByVal File_Name As String)
    
If Not (Stream Is Nothing) Then Return
     Stream = New FileStream(File_Name, FileMode.Open)
    
ReDim Data(Stream.Length)
     Stream.BeginRead(Data, 0, Stream.Length,
AddressOf Finished, Nothing)
     MessageBox.Show("BeginProcess")
End Sub

Private Sub Finished(ByVal Result As IAsyncResult)
    
Dim BytesRead = Stream.EndRead(Result)
     TextBox1.Text = System.Text.ASCIIEncoding.ASCII.GetString(Data)
     Stream.Close()
     Stream =
Nothing
    
MessageBox.Show("Finished")
End
Sub


First, on an unrelated note.  We are dealing with File IO so we are dealing with Bytes.  As such, Bytes aren't clearly readible for most people.  As such, we use AsciiEncoding to get the string representation of the bytes so we can set the Text property of the textbox to it.

This is all there is to it.  We create a stream object, open it for reading and get the lenght of the stream.  Then we invoke the file reading by passing in a Byte Array, the beginning point (0), the length of the stream and the AddressOf the method that will do the reading.  This calls Finished which handles the reading while other processing occurs.  So, if you run this, which MessageBox will you see first?  If you haven't read my first article, then you'll think you'll see BeginProcess first b/c this is Async reading and if we weren't using Async reading, we'd see Finished first then BeginProcess.  With this example, you'll see Finished first, then BeginProcess.  Huh?  Notice that we are using EndRead at the beginning and what does anything with End as a prefix do?  It blocks.

So, if we take out that line and change it to this, we get compeletely different sequence of events, yet the end result is the same.

Private Sub BeginProcess(ByVal File_Name As String)
    
If Not (Stream Is Nothing) Then Return
     Stream = New FileStream(File_Name, FileMode.Open)
    
ReDim Data(Stream.Length)
     Stream.BeginRead(Data, 0, Stream.Length,
AddressOf Finished, Nothing)
     MessageBox.Show("BeginProcess")
End Sub

Private Sub Finished(ByVal Result As IAsyncResult)
     TextBox1.Text = System.Text.ASCIIEncoding.ASCII.GetString(Data)
     Stream.Close()
     Stream =
Nothing
    
MessageBox.Show("Finished")
End
Sub


I'm going to cut this portion of the article short b/c this is pretty much all I wanted to discuss with IAsyncResult.  Threading is a very complex topic and I think we've laid the groundwork for it.  Once we get through that, I think you'll be in good shape to include Asynchronous programming in your repitoire.