Note

Access to this page requires authorization. You can try signing in or .

Access to this page requires authorization. You can try .

Using an AsyncCallback Delegate and State Object

When you use an AsyncCallback delegate to process the results of the asynchronous operation in a separate thread, you can use a state object to pass information between the callbacks and to retrieve a final result. This topic demonstrates that practice by expanding the example in Using an AsyncCallback Delegate to End an Asynchronous Operation.

Example

The following code example demonstrates using asynchronous methods in the Dns class to retrieve Domain Name System (DNS) information for user-specified computers. This example defines and uses the HostRequest class to store state information. A HostRequest object gets created for each computer name entered by the user. This object is passed to the BeginGetHostByName method. The ProcessDnsInformation method is called each time a request completes. The HostRequest object is retrieved using the AsyncState property. The ProcessDnsInformation method uses the HostRequest object to store the IPHostEntry returned by the request or a SocketException thrown by the request. When all requests are complete, the application iterates over the HostRequest objects and displays the DNS information or SocketException error message.

/*
The following example demonstrates using asynchronous methods to
get Domain Name System information for the specified host computer.
*/

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;

namespace Examples.AdvancedProgramming.AsynchronousOperations
{
// Create a state object that holds each requested host name,
// an associated IPHostEntry object or a SocketException.
 public class HostRequest
 {
 // Stores the requested host name.
 private string hostName;
 // Stores any SocketException returned by the Dns EndGetHostByName method.
 private SocketException e;
 // Stores an IPHostEntry returned by the Dns EndGetHostByName method.
 private IPHostEntry entry;

 public HostRequest(string name)
 {
 hostName = name;
 }

 public string HostName
 {
 get
 {
 return hostName;
 }
 }

 public SocketException ExceptionObject
 {
 get
 {
 return e;
 }
 set
 {
 e = value;
 }
 }

 public IPHostEntry HostEntry
 {
 get
 {
 return entry;
 }
 set
 {
 entry = value;
 }
 }
 }

 public class UseDelegateAndStateForAsyncCallback
 {
 // The number of pending requests.
 static int requestCounter;
 static ArrayList hostData = new ArrayList();
 static void UpdateUserInterface()
 {
 // Print a message to indicate that the application
 // is still working on the remaining requests.
 Console.WriteLine($"{requestCounter} requests remaining.");
 }
 public static void Main()
 {
 // Create the delegate that will process the results of the
 // asynchronous request.
 AsyncCallback callBack = new AsyncCallback(ProcessDnsInformation);
 string host;
 do
 {
 Console.Write(" Enter the name of a host computer or <enter> to finish: ");
 host = Console.ReadLine();
 if (host.Length > 0)
 {
 // Increment the request counter in a thread safe manner.
 Interlocked.Increment(ref requestCounter);
 // Create and store the state object for this request.
 HostRequest request = new HostRequest(host);
 hostData.Add(request);
 // Start the asynchronous request for DNS information.
 Dns.BeginGetHostEntry(host, callBack, request);
 }
 } while (host.Length > 0);
 // The user has entered all of the host names for lookup.
 // Now wait until the threads complete.
 while (requestCounter > 0)
 {
 UpdateUserInterface();
 }
 // Display the results.
 foreach(HostRequest r in hostData)
 {
 if (r.ExceptionObject != null)
 {
 Console.WriteLine($"Request for host {r.HostName} returned the following error: {r.ExceptionObject.Message}.");
 }
 else
 {
 // Get the results.
 IPHostEntry h = r.HostEntry;
 string[] aliases = h.Aliases;
 IPAddress[] addresses = h.AddressList;
 if (aliases.Length > 0)
 {
 Console.WriteLine($"Aliases for {r.HostName}");
 for (int j = 0; j < aliases.Length; j++)
 {
 Console.WriteLine($"{aliases[j]}");
 }
 }
 if (addresses.Length > 0)
 {
 Console.WriteLine($"Addresses for {r.HostName}");
 for (int k = 0; k < addresses.Length; k++)
 {
 Console.WriteLine($"{addresses[k].ToString()}");
 }
 }
 }
 }
 }

 // The following method is invoked when each asynchronous operation completes.
 static void ProcessDnsInformation(IAsyncResult result)
 {
 // Get the state object associated with this request.
 HostRequest request = (HostRequest) result.AsyncState;
 try
 {
 // Get the results and store them in the state object.
 IPHostEntry host = Dns.EndGetHostEntry(result);
 request.HostEntry = host;
 }
 catch (SocketException e)
 {
 // Store any SocketExceptions.
 request.ExceptionObject = e;
 }
 finally
 {
 // Decrement the request counter in a thread-safe manner.
 Interlocked.Decrement(ref requestCounter);
 }
 }
 }
}
' The following example demonstrates using asynchronous methods to
' get Domain Name System information for the specified host computer.

Imports System.Net
Imports System.Net.Sockets
Imports System.Threading
Imports System.Collections

Namespace Examples.AdvancedProgramming.AsynchronousOperations
 ' Create a state object that holds each requested host name, 
 ' an associated IPHostEntry object or a SocketException.
 Public Class HostRequest
 ' Stores the requested host name.
 Dim hostNameValue as string
 ' Stores any SocketException returned by the Dns EndGetHostByName method.
 Dim e as SocketException
 ' Stores an IPHostEntry returned by the Dns EndGetHostByName method.
 Dim entry as IPHostEntry

 Public Sub New(name as String)
 hostNameValue = name
 End Sub

 ReadOnly Public Property HostName as String
 Get
 return hostNameValue
 End Get
 End Property

 Public Property ExceptionObject as SocketException
 Get
 return e
 End Get
 Set
 e = value
 End Set
 End Property

 Public Property HostEntry as IPHostEntry
 Get
 return entry
 End Get
 Set
 entry = value
 End Set
 End Property
 End Class

 Public Class UseDelegateAndStateForAsyncCallback
 ' The number of pending requests.
 Dim Shared requestCounter as Integer
 Dim Shared hostData as ArrayList = new ArrayList()

 Shared Sub UpdateUserInterface()
 ' Print a message to indicate that the application
 ' is still working on the remaining requests.
 Console.WriteLine("{0} requests remaining.", requestCounter)
 End Sub

 Public Shared Sub Main()
 ' Create the delegate that will process the results of the 
 ' asynchronous request.
 Dim callBack as AsyncCallback = AddressOf ProcessDnsInformation
 Dim host as string

 Do
 Console.Write(" Enter the name of a host computer or <enter> to finish: ")
 host = Console.ReadLine()
 If host.Length > 0
 ' Increment the request counter in a thread safe manner.
 Interlocked.Increment(requestCounter)
 ' Create and store the state object for this request.
 Dim request as HostRequest = new HostRequest(host)
 hostData.Add(request)
 ' Start the asynchronous request for DNS information.
 Dns.BeginGetHostEntry(host, callBack, request)
 End If
 Loop While host.Length > 0

 ' The user has entered all of the host names for lookup.
 ' Now wait until the threads complete.
 Do While requestCounter > 0
 UpdateUserInterface()
 Loop

 ' Display the results.
 For Each r as HostRequest In hostData
 If IsNothing(r.ExceptionObject) = False
 Console.WriteLine( _
 "Request for host {0} returned the following error: {1}.", _
 r.HostName, r.ExceptionObject.Message)
 Else
 ' Get the results.
 Dim h as IPHostEntry = r.HostEntry
 Dim aliases() as String = h.Aliases
 Dim addresses() as IPAddress = h.AddressList
 Dim j, k as Integer

 If aliases.Length > 0
 Console.WriteLine("Aliases for {0}", r.HostName)
 For j = 0 To aliases.Length - 1
 Console.WriteLine("{0}", aliases(j))
 Next j
 End If
 If addresses.Length > 0
 Console.WriteLine("Addresses for {0}", r.HostName)
 For k = 0 To addresses.Length - 1
 Console.WriteLine("{0}", addresses(k).ToString())
 Next k
 End If
 End If
 Next r
 End Sub

 ' The following method is invoked when each asynchronous operation completes.
 Shared Sub ProcessDnsInformation(result as IAsyncResult)
 ' Get the state object associated with this request.
 Dim request as HostRequest = CType(result.AsyncState, HostRequest)
 Try
 ' Get the results and store them in the state object.
 Dim host as IPHostEntry = Dns.EndGetHostEntry(result)
 request.HostEntry = host
 Catch e as SocketException
 ' Store any SocketExceptions.
 request.ExceptionObject = e
 Finally
 ' Decrement the request counter in a thread-safe manner.
 Interlocked.Decrement(requestCounter)
 End Try
 End Sub
 End Class
End Namespace

See also


Feedback

Was this page helpful?

Additional resources