使用 AsyncCallback 委托和状态对象
在等待异步操作结果的同时可以进行其他工作的应用程序不应在操作完成之前阻止等待。 可以使用下列方法之一来在等待异步操作完成的同时继续执行指令。
可使用 AsyncCallback 委托来处理另一个线程中的异步操作的结果。 本主题中演示了此方法。
可使用异步操作的 Begin操作名称 方法返回的 IAsyncResult 的 IsCompleted 属性来确定该操作是否已完成。 有关演示此方法的示例,请参见 轮询异步操作的状态。
示例
下面的代码示例演示如何使用 Dns 类中的异步方法来检索用户指定的计算机的域名系统 (DNS) 信息。 此示例定义了 HostRequest 类并使用该类来存储状态信息。 此示例中为用户输入的每个计算机名都创建了一个 HostRequest 对象。 此对象被传递给了 BeginGetHostByName 方法。 每当请求完成时,都会调用 ProcessDnsInformation 方法。 可使用 AsyncState 属性来检索 HostRequest 对象。 ProcessDnsInformation 方法使用 HostRequest 对象来存储请求返回的 IPHostEntry 或请求引发的 SocketException。 当所有的请求都完成后,应用程序会循环访问 HostRequest 对象,显示 DNS 信息或 SocketException 错误信息。
' The following example demonstrates using asynchronous methods to
' get Domain Name System information for the specified host computer.
Imports System
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
/*
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("{0} requests remaining.", requestCounter);
}
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 {0} returned the following error: {1}.",
r.HostName, 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 {0}", r.HostName);
for (int j = 0; j < aliases.Length; j++)
{
Console.WriteLine("{0}", aliases[j]);
}
}
if (addresses.Length > 0)
{
Console.WriteLine("Addresses for {0}", r.HostName);
for (int k = 0; k < addresses.Length; k++)
{
Console.WriteLine("{0}",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);
}
}
}
}