home *** CD-ROM | disk | FTP | other *** search
- Imports System.Threading
-
- Module MainModule
-
- Sub Main()
- ' Run one of the Textxxxx procedures below by uncommenting only one statement
- 'TestSynchronousCall()
- 'TestAsynchronousCall()
- 'TestMultiAsynchronousCall()
- 'TestAsynchronousCallback()
- 'TestOneWayAttribute()
- 'TestAsyncFileOperations()
-
- ' You need these statements when running inside Visual Studio, so that
- ' the Console window doesn't disappear
- Console.WriteLine("")
- Console.WriteLine(">>> Press Enter to terminate the program <<<")
- Console.ReadLine()
- End Sub
-
- ' this procedure scans a directory tree for a file
- ' it takes a path and a file specification, and returns an array of filenames
- ' in the 3rd arguent it returns the number of directories that have been parsed.
-
- <ThreadStatic()> _
- Dim nestLevel As Integer
-
- Function FindFiles(ByVal path As String, ByVal fileSpec As String, ByRef parsedDirs As Integer) As ArrayList
- ' this variable keeps track of nesting level
- Dim subdir As String
-
- ' if this is the first call, reset number of parsed directories.
- If nestLevel = 0 Then parsedDirs = 0
-
- ' Prepare the result ArrayList.
- FindFiles = New ArrayList()
-
- nestLevel += 1
-
- ' Put everything in Try...End Try, so that we are sure that
- ' nestLevel is correctly decremented if an error occurs
- Try
- ' Get all files in this directory that match the file spec.
- ' (This statement is valid because GetFiles returns a String array,
- ' which implements ICollection)
- FindFiles.AddRange(System.IO.Directory.GetFiles(path, fileSpec))
- ' Remember that a directory has been parsed
- parsedDirs += 1
-
- ' Uncomment next statement to prove that multiple async calls to this routine
- ' are actually executed serially.
- 'Debug.WriteLine(path & " (thread = " & AppDomain.GetCurrentThreadId.ToString & ")")
-
- ' Scan subdirectories.
- For Each subdir In System.IO.Directory.GetDirectories(path)
- ' add all the matching files in sub directories
- FindFiles.AddRange(FindFiles(subdir, fileSpec, parsedDirs))
- Next
- Finally
- nestLevel -= 1
- End Try
- End Function
-
- ' this procedure tests FindFiles in synchronous mode
-
- Sub TestSynchronousCall()
- Dim parsedDirs As Integer
-
- ' find *.txt files in the C:\DOCS directory tree.
- Dim files As ArrayList = FindFiles("c:\docs", "*.txt", parsedDirs)
- Dim file As String
- For Each file In files
- Console.WriteLine(file)
- Next
- ' use the output argument.
- Console.WriteLine(" {0} directories have been parsed.", parsedDirs)
- End Sub
-
- ' a delegate that points to FindFiles
- Delegate Function FindFilesDelegate(ByVal path As String, ByVal fileSpec As String, ByRef parsedDirs As Integer) As ArrayList
-
- ' this procedure calls FindFiles asynchronously, and polls until it returns.
-
- Sub TestAsynchronousCall()
- Dim parsedDirs As Integer
-
- ' Create a delegate that points to target procedure.
- Dim findFilesDeleg As New FindFilesDelegate(AddressOf FindFiles)
-
- ' Start the asynchronous call, get an IAsynchResult object.
- Dim ar As IAsyncResult = findFilesDeleg.BeginInvoke("c:\docs", "*.txt", parsedDirs, Nothing, Nothing)
-
- ' wait until the method Completes its execution.
- Do Until ar.IsCompleted
- Console.WriteLine("The main thread is waiting for FindFiles results.")
- Thread.Sleep(500)
- Loop
-
- ' Now you can get the results.
- Dim files As ArrayList = findFilesDeleg.EndInvoke(parsedDirs, ar)
-
- Dim file As String
- For Each file In files
- Console.WriteLine(file)
- Next
- Console.WriteLine(" {0} directories have been parsed.", parsedDirs)
- End Sub
-
- ' this procedure runs two methods asynchronously, and waits for their completion
-
- Sub TestMultiAsynchronousCall()
- ' we must run the operation in another thread.
- Dim tr As New Thread(AddressOf TestMultiAsynchronousCall_Sub)
- tr.Start()
- tr.Join()
- End Sub
-
- ' support routine for previous test procedure
-
- Sub TestMultiAsynchronousCall_Sub()
- Dim parsedDirs(1) As Integer
- Dim ar(1) As IAsyncResult
-
- ' Create a delegate that points to target procedure.
- Dim findFilesDeleg As New FindFilesDelegate(AddressOf FindFiles)
-
- ' Start the asynchronous call, get an IAsynchResult object.
- ar(0) = findFilesDeleg.BeginInvoke("c:\books", "*.txt", parsedDirs(0), Nothing, Nothing)
- Console.WriteLine("Started the first asynchronous search")
- ar(1) = findFilesDeleg.BeginInvoke("c:\docs", "*.txt", parsedDirs(1), Nothing, Nothing)
- Console.WriteLine("Started the second asynchronous search")
-
- ' create an array of WaitHandle objects.
- Dim waitHandles() As WaitHandle = {ar(0).AsyncWaitHandle, ar(1).AsyncWaitHandle}
-
- ' wait until all methods complete
- Do Until WaitHandle.WaitAll(waitHandles, 500, False)
- Console.WriteLine("The main thread is waiting for all FindFiles results.")
- Loop
-
- ' Now you can get the results.
- Dim files As ArrayList = findFilesDeleg.EndInvoke(parsedDirs(0), ar(0))
- ' Append results from second method.
- files.AddRange(findFilesDeleg.EndInvoke(parsedDirs(1), ar(1)))
-
- Dim file As String
- For Each file In files
- Console.WriteLine(file)
- Next
- Console.WriteLine(" {0} directories have been parsed.", parsedDirs(0) + parsedDirs(1))
- End Sub
-
- ' this procedure tests asynchronous callbacks
-
- Sub TestAsynchronousCallback()
- Dim parsedDirs As Integer
-
- ' Create a delegate that points to target procedure.
- Dim findFilesDeleg As New FindFilesDelegate(AddressOf FindFiles)
-
- ' create a cookie object, pass it an ID and the delegate
- ' just to show that this object can be accessed in the callback procedure
- Dim cookieObj As New Cookie("a sample async call", findFilesDeleg)
-
- ' Start the asynchronous call, pass a delegate to the MethodCompleted procedure.
- ' get an IAsynchResult object.
- Dim ar As IAsyncResult = findFilesDeleg.BeginInvoke("c:\docs", "*.txt", parsedDirs, New AsyncCallback(AddressOf MethodCompleted), cookieObj)
-
- ' in this demo we wait for some seconds, to postpone the "Press any key" message
- Thread.Sleep(5000)
-
- End Sub
-
- ' this is the callback method
-
- Sub MethodCompleted(ByVal ar As IAsyncResult)
- ' get the cookie object, display its ID (just to show its that very object)
- Dim cookieObj As Cookie = DirectCast(ar.AsyncState, Cookie)
-
- Console.WriteLine("Cookie ID = {0}", cookieObj.Id)
- Console.WriteLine("")
-
- ' get a reference to the original delegate
- Dim deleg As FindFilesDelegate = DirectCast(cookieObj.AsycnDelegate, FindFilesDelegate)
-
- ' call the EndInvoke method, get the return value
- Dim parsedDirs As Integer
- Dim files As ArrayList = deleg.EndInvoke(parsedDirs, ar)
-
- Dim file As String
- For Each file In files
- Console.WriteLine(file)
- Next
- Console.WriteLine(" {0} directories have been parsed.", parsedDirs)
- End Sub
-
- ' this procedure tests the OneWay attribute with a method that throws an exception
-
- Sub TestOneWayAttribute()
- ' a delegate to a method that throws an exception
- Dim deleg As New MethodDelegate(AddressOf MethodThatThrows)
- ' call it asynchronously
- Dim ar As IAsyncResult = deleg.BeginInvoke(Nothing, Nothing, Nothing)
- ' wait until it completes
- ar.AsyncWaitHandle.WaitOne()
-
- Try
- Console.WriteLine("Calling EndInvoke on a regular method")
- deleg.EndInvoke(ar)
- Console.WriteLine("The EndInvoke method didn't throw an exception")
- Catch ex As Exception
- Console.WriteLine("The EndInvoke method threw an exception")
- End Try
-
- ' Now do the same with a method marked with OneWayAttribute.
-
- ' a delegate to a method that throws an exception
- deleg = New MethodDelegate(AddressOf MethodThatThrowsWithOneWayAttribute)
- ' call it asynchronously
- ar = deleg.BeginInvoke(Nothing, Nothing, Nothing)
- ' wait until it completes
- ar.AsyncWaitHandle.WaitOne()
-
- Try
- Console.WriteLine("")
- Console.WriteLine("Calling EndInvoke on a method marked with OneWayAttribute")
- deleg.EndInvoke(ar)
- Console.WriteLine("The EndInvoke method didn't throw an exception")
- Catch ex As Exception
- Console.WriteLine("The EndInvoke method threw an exception")
- End Try
-
- End Sub
-
- Delegate Sub MethodDelegate(ByVal anArgument As Object)
-
- ' here's method that throws an exception
-
- Sub MethodThatThrows(ByVal anArgument As Object)
- Throw New ArgumentException()
- End Sub
-
- ' here's another similar method, but it is marked with the OneWayAttribute
- <System.Runtime.Remoting.Messaging.OneWay()> _
- Sub MethodThatThrowsWithOneWayAttribute(ByVal anArgument As Object)
- Throw New ArgumentException()
- End Sub
-
- ' the file being read from/written to
- Const FileName As String = "C:\TESTDATA.TMP"
- ' the FileStream object used to both reading and writing
- Dim fs As System.IO.FileStream
- ' the buffer to do file I/O
- Dim buffer() As Byte
-
- ' this procedure tests asynchronous file read
-
- Sub TestAsyncFileOperations()
- Dim i As Integer
- Dim ar As IAsyncResult
-
- ' fill the buffer with 1M of random data
- ReDim buffer(1048575)
- For i = 0 To UBound(buffer)
- buffer(i) = CByte(i Mod 256)
- Next
-
- ' create the target file in asynchronous mode (open in asynchronous mode)
- fs = New System.IO.FileStream(FileName, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None, 65536, True)
- ' start the async write operation
- Console.WriteLine("Starting the async write operation")
- ar = fs.BeginWrite(buffer, 0, UBound(buffer) + 1, AddressOf AsyncFileCallback, "write")
-
- ' wait a few seconds until the operation completes
- Thread.Sleep(4000)
-
- ' now read the file back (open in asynchronous mode)
- fs = New System.IO.FileStream(FileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None, 65536, True)
- ' dimension the receiving buffer
- ReDim buffer(CInt(fs.Length) - 1)
- ' start the async read operation
- Console.WriteLine("")
- Console.WriteLine("Starting the async read operation")
- ar = fs.BeginRead(buffer, 0, UBound(buffer) + 1, AddressOf AsyncFileCallback, "read")
-
- ' wait a few seconds until the operation completes
- Thread.Sleep(4000)
- End Sub
-
- ' this is the call back procedure for both async read and write
-
- Sub AsyncFileCallback(ByVal ar As IAsyncResult)
- ' get the state object (the "write" or "read" string)
- Dim opName As String = ar.AsyncState.ToString
-
- ' the behavior is quite different in the two cases.
- Select Case opName
- Case "write"
- Console.WriteLine("Async write operation completed")
- ' complete the write and close the stream
- fs.EndWrite(ar)
- fs.Close()
- Case "read"
- Console.WriteLine("Async read operation completed")
- ' complete the read and close the stream
- Dim bytes As Integer = fs.EndRead(ar)
- Console.WriteLine(fs.IsAsync)
- Console.WriteLine("Read {0} bytes", bytes)
- fs.Close()
-
- ' check that each byte was read back correctly
- Dim i As Integer, wrongData As Boolean
- For i = 0 To UBound(buffer)
- If buffer(i) <> CInt(i Mod 256) Then wrongData = True
- Next
- If wrongData Then
- Console.WriteLine("Error while reading back data")
- Else
- Console.WriteLine("Data was read back correctly")
- End If
-
- End Select
-
- End Sub
-
- End Module
-
- ' this class is used to demo Async Callbacks
-
- Class Cookie
- Public Id As String
- Public AsycnDelegate As [Delegate]
-
- Sub New(ByVal id As String, ByVal asyncDelegate As [Delegate])
- Me.Id = id
- Me.AsycnDelegate = asyncDelegate
- End Sub
- End Class