home *** CD-ROM | disk | FTP | other *** search
/ Programming Microsoft Visual Basic .NET / Programming Microsoft Visual Basic .NET (Microsoft Press)(X08-78517)(2002).bin / setup / vbnet / 13 threading / asynchronousoperations / module1.vb < prev   
Encoding:
Text File  |  2002-03-20  |  12.8 KB  |  338 lines

  1. Imports System.Threading
  2.  
  3. Module MainModule
  4.  
  5.     Sub Main()
  6.         ' Run one of the Textxxxx procedures below by uncommenting only one statement
  7.         'TestSynchronousCall()
  8.         'TestAsynchronousCall()
  9.         'TestMultiAsynchronousCall()
  10.         'TestAsynchronousCallback()
  11.         'TestOneWayAttribute()
  12.         'TestAsyncFileOperations()
  13.  
  14.         ' You need these statements when running inside Visual Studio, so that
  15.         ' the Console window doesn't disappear
  16.         Console.WriteLine("")
  17.         Console.WriteLine(">>> Press Enter to terminate the program <<<")
  18.         Console.ReadLine()
  19.     End Sub
  20.  
  21.     ' this procedure scans a directory tree for a file
  22.     ' it takes a path and a file specification, and returns an array of filenames
  23.     ' in the 3rd arguent it returns the number of directories that have been parsed.
  24.  
  25.     <ThreadStatic()> _
  26.     Dim nestLevel As Integer
  27.  
  28.     Function FindFiles(ByVal path As String, ByVal fileSpec As String, ByRef parsedDirs As Integer) As ArrayList
  29.         ' this variable keeps track of nesting level
  30.         Dim subdir As String
  31.  
  32.         ' if this is the first call, reset number of parsed directories.
  33.         If nestLevel = 0 Then parsedDirs = 0
  34.  
  35.         ' Prepare the result ArrayList.
  36.         FindFiles = New ArrayList()
  37.  
  38.         nestLevel += 1
  39.  
  40.         ' Put everything in Try...End Try, so that we are sure that
  41.         ' nestLevel is correctly decremented if an error occurs
  42.         Try
  43.             ' Get all files in this directory that match the file spec.
  44.             ' (This statement is valid because GetFiles returns a String array, 
  45.             '  which implements ICollection)
  46.             FindFiles.AddRange(System.IO.Directory.GetFiles(path, fileSpec))
  47.             ' Remember that a directory has been parsed
  48.             parsedDirs += 1
  49.  
  50.             ' Uncomment next statement to prove that multiple async calls to this routine
  51.             ' are actually executed serially.
  52.             'Debug.WriteLine(path & " (thread = " & AppDomain.GetCurrentThreadId.ToString & ")")
  53.  
  54.             ' Scan subdirectories.
  55.             For Each subdir In System.IO.Directory.GetDirectories(path)
  56.                 ' add all the matching files in sub directories
  57.                 FindFiles.AddRange(FindFiles(subdir, fileSpec, parsedDirs))
  58.             Next
  59.         Finally
  60.             nestLevel -= 1
  61.         End Try
  62.     End Function
  63.  
  64.     ' this procedure tests FindFiles in synchronous mode
  65.  
  66.     Sub TestSynchronousCall()
  67.         Dim parsedDirs As Integer
  68.  
  69.         ' find *.txt files in the C:\DOCS directory tree.
  70.         Dim files As ArrayList = FindFiles("c:\docs", "*.txt", parsedDirs)
  71.         Dim file As String
  72.         For Each file In files
  73.             Console.WriteLine(file)
  74.         Next
  75.         ' use the output argument.
  76.         Console.WriteLine("  {0} directories have been parsed.", parsedDirs)
  77.     End Sub
  78.  
  79.     ' a delegate that points to FindFiles
  80.     Delegate Function FindFilesDelegate(ByVal path As String, ByVal fileSpec As String, ByRef parsedDirs As Integer) As ArrayList
  81.  
  82.     ' this procedure calls FindFiles asynchronously, and polls until it returns.
  83.  
  84.     Sub TestAsynchronousCall()
  85.         Dim parsedDirs As Integer
  86.  
  87.         ' Create a delegate that points to target procedure.
  88.         Dim findFilesDeleg As New FindFilesDelegate(AddressOf FindFiles)
  89.  
  90.         ' Start the asynchronous call, get an IAsynchResult object.
  91.         Dim ar As IAsyncResult = findFilesDeleg.BeginInvoke("c:\docs", "*.txt", parsedDirs, Nothing, Nothing)
  92.  
  93.         ' wait until the method Completes its execution.
  94.         Do Until ar.IsCompleted
  95.             Console.WriteLine("The main thread is waiting for FindFiles results.")
  96.             Thread.Sleep(500)
  97.         Loop
  98.  
  99.         ' Now you can get the results.
  100.         Dim files As ArrayList = findFilesDeleg.EndInvoke(parsedDirs, ar)
  101.  
  102.         Dim file As String
  103.         For Each file In files
  104.             Console.WriteLine(file)
  105.         Next
  106.         Console.WriteLine("  {0} directories have been parsed.", parsedDirs)
  107.     End Sub
  108.  
  109.     ' this procedure runs two methods asynchronously, and waits for their completion
  110.  
  111.     Sub TestMultiAsynchronousCall()
  112.         ' we must run the operation in another thread.
  113.         Dim tr As New Thread(AddressOf TestMultiAsynchronousCall_Sub)
  114.         tr.Start()
  115.         tr.Join()
  116.     End Sub
  117.  
  118.     ' support routine for previous test procedure
  119.  
  120.     Sub TestMultiAsynchronousCall_Sub()
  121.         Dim parsedDirs(1) As Integer
  122.         Dim ar(1) As IAsyncResult
  123.  
  124.         ' Create a delegate that points to target procedure.
  125.         Dim findFilesDeleg As New FindFilesDelegate(AddressOf FindFiles)
  126.  
  127.         ' Start the asynchronous call, get an IAsynchResult object.
  128.         ar(0) = findFilesDeleg.BeginInvoke("c:\books", "*.txt", parsedDirs(0), Nothing, Nothing)
  129.         Console.WriteLine("Started the first asynchronous search")
  130.         ar(1) = findFilesDeleg.BeginInvoke("c:\docs", "*.txt", parsedDirs(1), Nothing, Nothing)
  131.         Console.WriteLine("Started the second asynchronous search")
  132.  
  133.         ' create an array of WaitHandle objects.
  134.         Dim waitHandles() As WaitHandle = {ar(0).AsyncWaitHandle, ar(1).AsyncWaitHandle}
  135.  
  136.         ' wait until all methods complete
  137.         Do Until WaitHandle.WaitAll(waitHandles, 500, False)
  138.             Console.WriteLine("The main thread is waiting for all FindFiles results.")
  139.         Loop
  140.  
  141.         ' Now you can get the results.
  142.         Dim files As ArrayList = findFilesDeleg.EndInvoke(parsedDirs(0), ar(0))
  143.         ' Append results from second method.
  144.         files.AddRange(findFilesDeleg.EndInvoke(parsedDirs(1), ar(1)))
  145.  
  146.         Dim file As String
  147.         For Each file In files
  148.             Console.WriteLine(file)
  149.         Next
  150.         Console.WriteLine("  {0} directories have been parsed.", parsedDirs(0) + parsedDirs(1))
  151.     End Sub
  152.  
  153.     ' this procedure tests asynchronous callbacks
  154.  
  155.     Sub TestAsynchronousCallback()
  156.         Dim parsedDirs As Integer
  157.  
  158.         ' Create a delegate that points to target procedure.
  159.         Dim findFilesDeleg As New FindFilesDelegate(AddressOf FindFiles)
  160.  
  161.         ' create a cookie object, pass it an ID and the delegate
  162.         ' just to show that this object can be accessed in the callback procedure
  163.         Dim cookieObj As New Cookie("a sample async call", findFilesDeleg)
  164.  
  165.         ' Start the asynchronous call, pass a delegate to the MethodCompleted procedure.
  166.         ' get an IAsynchResult object.
  167.         Dim ar As IAsyncResult = findFilesDeleg.BeginInvoke("c:\docs", "*.txt", parsedDirs, New AsyncCallback(AddressOf MethodCompleted), cookieObj)
  168.  
  169.         ' in this demo we wait for some seconds, to postpone the "Press any key" message
  170.         Thread.Sleep(5000)
  171.  
  172.     End Sub
  173.  
  174.     ' this is the callback method
  175.  
  176.     Sub MethodCompleted(ByVal ar As IAsyncResult)
  177.         ' get the cookie object, display its ID (just to show its that very object)
  178.         Dim cookieObj As Cookie = DirectCast(ar.AsyncState, Cookie)
  179.  
  180.         Console.WriteLine("Cookie ID = {0}", cookieObj.Id)
  181.         Console.WriteLine("")
  182.  
  183.         ' get a reference to the original delegate
  184.         Dim deleg As FindFilesDelegate = DirectCast(cookieObj.AsycnDelegate, FindFilesDelegate)
  185.  
  186.         ' call the EndInvoke method, get the return value
  187.         Dim parsedDirs As Integer
  188.         Dim files As ArrayList = deleg.EndInvoke(parsedDirs, ar)
  189.  
  190.         Dim file As String
  191.         For Each file In files
  192.             Console.WriteLine(file)
  193.         Next
  194.         Console.WriteLine("  {0} directories have been parsed.", parsedDirs)
  195.     End Sub
  196.  
  197.     ' this procedure tests the OneWay attribute with a method that throws an exception
  198.  
  199.     Sub TestOneWayAttribute()
  200.         ' a delegate to a method that throws an exception
  201.         Dim deleg As New MethodDelegate(AddressOf MethodThatThrows)
  202.         ' call it asynchronously
  203.         Dim ar As IAsyncResult = deleg.BeginInvoke(Nothing, Nothing, Nothing)
  204.         ' wait until it completes
  205.         ar.AsyncWaitHandle.WaitOne()
  206.  
  207.         Try
  208.             Console.WriteLine("Calling EndInvoke on a regular method")
  209.             deleg.EndInvoke(ar)
  210.             Console.WriteLine("The EndInvoke method didn't throw an exception")
  211.         Catch ex As Exception
  212.             Console.WriteLine("The EndInvoke method threw an exception")
  213.         End Try
  214.  
  215.         ' Now do the same with a method marked with OneWayAttribute.
  216.  
  217.         ' a delegate to a method that throws an exception
  218.         deleg = New MethodDelegate(AddressOf MethodThatThrowsWithOneWayAttribute)
  219.         ' call it asynchronously
  220.         ar = deleg.BeginInvoke(Nothing, Nothing, Nothing)
  221.         ' wait until it completes
  222.         ar.AsyncWaitHandle.WaitOne()
  223.  
  224.         Try
  225.             Console.WriteLine("")
  226.             Console.WriteLine("Calling EndInvoke on a method marked with OneWayAttribute")
  227.             deleg.EndInvoke(ar)
  228.             Console.WriteLine("The EndInvoke method didn't throw an exception")
  229.         Catch ex As Exception
  230.             Console.WriteLine("The EndInvoke method threw an exception")
  231.         End Try
  232.  
  233.     End Sub
  234.  
  235.     Delegate Sub MethodDelegate(ByVal anArgument As Object)
  236.  
  237.     ' here's method that throws an exception
  238.  
  239.     Sub MethodThatThrows(ByVal anArgument As Object)
  240.         Throw New ArgumentException()
  241.     End Sub
  242.  
  243.     ' here's another similar method, but it is marked with the OneWayAttribute
  244.     <System.Runtime.Remoting.Messaging.OneWay()> _
  245.     Sub MethodThatThrowsWithOneWayAttribute(ByVal anArgument As Object)
  246.         Throw New ArgumentException()
  247.     End Sub
  248.  
  249.     ' the file being read from/written to
  250.     Const FileName As String = "C:\TESTDATA.TMP"
  251.     ' the FileStream object used to both reading and writing
  252.     Dim fs As System.IO.FileStream
  253.     ' the buffer to do file I/O
  254.     Dim buffer() As Byte
  255.  
  256.     ' this procedure tests asynchronous file read
  257.  
  258.     Sub TestAsyncFileOperations()
  259.         Dim i As Integer
  260.         Dim ar As IAsyncResult
  261.  
  262.         ' fill the buffer with 1M of random data
  263.         ReDim buffer(1048575)
  264.         For i = 0 To UBound(buffer)
  265.             buffer(i) = CByte(i Mod 256)
  266.         Next
  267.  
  268.         ' create the target file in asynchronous mode (open in asynchronous mode)
  269.         fs = New System.IO.FileStream(FileName, IO.FileMode.Create, IO.FileAccess.Write, IO.FileShare.None, 65536, True)
  270.         ' start the async write operation
  271.         Console.WriteLine("Starting the async write operation")
  272.         ar = fs.BeginWrite(buffer, 0, UBound(buffer) + 1, AddressOf AsyncFileCallback, "write")
  273.  
  274.         ' wait a few seconds until the operation completes
  275.         Thread.Sleep(4000)
  276.  
  277.         ' now read the file back (open in asynchronous mode)
  278.         fs = New System.IO.FileStream(FileName, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.None, 65536, True)
  279.         ' dimension the receiving buffer
  280.         ReDim buffer(CInt(fs.Length) - 1)
  281.         ' start the async read operation
  282.         Console.WriteLine("")
  283.         Console.WriteLine("Starting the async read operation")
  284.         ar = fs.BeginRead(buffer, 0, UBound(buffer) + 1, AddressOf AsyncFileCallback, "read")
  285.  
  286.         ' wait a few seconds until the operation completes
  287.         Thread.Sleep(4000)
  288.     End Sub
  289.  
  290.     ' this is the call back procedure for both async read and write
  291.  
  292.     Sub AsyncFileCallback(ByVal ar As IAsyncResult)
  293.         ' get the state object (the "write" or "read" string)
  294.         Dim opName As String = ar.AsyncState.ToString
  295.  
  296.         ' the behavior is quite different in the two cases.
  297.         Select Case opName
  298.             Case "write"
  299.                 Console.WriteLine("Async write operation completed")
  300.                 ' complete the write and close the stream
  301.                 fs.EndWrite(ar)
  302.                 fs.Close()
  303.             Case "read"
  304.                 Console.WriteLine("Async read operation completed")
  305.                 ' complete the read and close the stream
  306.                 Dim bytes As Integer = fs.EndRead(ar)
  307.                 Console.WriteLine(fs.IsAsync)
  308.                 Console.WriteLine("Read {0} bytes", bytes)
  309.                 fs.Close()
  310.  
  311.                 ' check that each byte was read back correctly
  312.                 Dim i As Integer, wrongData As Boolean
  313.                 For i = 0 To UBound(buffer)
  314.                     If buffer(i) <> CInt(i Mod 256) Then wrongData = True
  315.                 Next
  316.                 If wrongData Then
  317.                     Console.WriteLine("Error while reading back data")
  318.                 Else
  319.                     Console.WriteLine("Data was read back correctly")
  320.                 End If
  321.  
  322.         End Select
  323.  
  324.     End Sub
  325.  
  326. End Module
  327.  
  328. ' this class is used to demo Async Callbacks
  329.  
  330. Class Cookie
  331.     Public Id As String
  332.     Public AsycnDelegate As [Delegate]
  333.  
  334.     Sub New(ByVal id As String, ByVal asyncDelegate As [Delegate])
  335.         Me.Id = id
  336.         Me.AsycnDelegate = asyncDelegate
  337.     End Sub
  338. End Class