使用 IASyncResult 设计模式的异步操作是通过名为 BeginOperationName
和 EndOperationName
的两个方法来实现的,这两个方法分别开始和结束异步操作 OperationName。在调用 BeginOperationName
后,应用程序可以继续在调用线程上执行,同时异步操作在另一个线程上执行。 应用程序还应通过调用 EndOperationName
来获取异步操作的结果。
BeginOperationName
方法开始异步操作 OperationName,并返回实现 IASyncResult 接口的对象。IASyncResult 对象存储有关异步操作的信息。
成员 | 类型 | 说明 |
---|---|---|
AsyncState | object | 一个特定于应用程序的可选对象,其中包含有关异步操作的信息。 |
AsyncWaitHandle | System.Threading.WaitHandle | 一个 WaitHandle,可用来在异步操作完成之前阻止应用程序执行。 |
CompletedSynchronously | bool | 一个值,指示异步操作是否是在用于调用 BeginOperationName 的线程上完成,而不是在单独的 ThreadPool 线程上完成。 |
IsCompleted | bool | 一个值,指示异步操作是否已完成。 |
BeginOperationName
方法采用该方法的同步版本的签名中声明的任何参数(由值传递或由引用传递)。 BeginOperationName
方法签名中不包含任何输出参数。 BeginOperationName
方法签名另外还包括两个其他参数。
null
。BeginOperationName
方法还采用其他一些操作特定的参数(例如,一个用于存储从文件读取的字节的字节数组),则 AsyncCallback 和应用程序状态对象将是 BeginOperationName
方法签名中的最后两个参数。BeginOperationName
立即返回对调用线程的控制。 如果 BeginOperationName
方法引发异常,则会在开始异步操作之前引发异常。 如果 BeginOperationName
方法引发异常,则意味着没有调用回调方法。
EndOperationName
方法用于结束异步操作 OperationName。 EndOperationName
方法的返回值与其同步对应方法的返回值类型相同,并且是特定于异步操作的。 例如,EndRead 方法返回从 FileStream 读取的字节数, EndGetHostByName 方法返回包含有关主机的信息的 IPHostEntry 对象。EndOperationName
方法采用该方法同步版本的签名中声明的所有输出参数或引用参数。 除了来自同步方法的参数外,EndOperationName
方法还包括 IASyncResult 参数。 调用方必须将对应调用返回的实例传递给 BeginOperationName
。
如果调用 EndOperationName
时 IASyncResult 对象表示的异步操作尚未完成,则 EndOperationName
将在异步操作完成之前阻止调用线程。 异步操作引发的异常是从 EndOperationName
方法引发的。
EndOperationName
方法的效果EndOperationName
方法的效果对于这两种未定义的情况,实施者应考虑引发 InvalidOperationException。此设计模式的实施者应通知调用方异步操作已通过以下步骤完成:将 IsCompeleted 设置为 true,调用异步回调方法(如果已指定一个回调方法),然后发送 AsyncWaitHandle信号。
正确的选择取决于应用程序是否有可以在操作完成时执行的指令。 如果应用程序在接收到异步操作结果之前不能进行任何其他工作,则必须在获得这些结果之前先阻止该应用程序进行其他工作。 若要在异步操作完成之前阻止应用程序,可以使用下列方法之一:
从应用程序的主线程调用 EndOperationName
,阻止应用程序执行,直到操作完成之后再继续执行。
使用 AsyncWaitHandle 来阻止应用程序执行,直到一个或多个操作完成。
在异步操作完成时不需要阻止的应用程序可使用下列方法之一:
按以下方式轮询操作完成状态:定期检查 IsCompleted 属性,操作完成后调用 EndOperationName
。
使用 AsyncCallback 委托来指定要在操作完成时调用的方法。
如果应用无法在等待异步操作结果期间继续执行其他工作,必须阻止应用一直到操作完成。 可以使用以下两种方式在应用等待异步操作完成期间阻止应用的主线程:
使用异步操作的 BeginOperationName 方法返回的 IAsyncResult 的 AsyncWaitHandle 属性。
在应用程序的主线程上调用EndOperationName
在异步操作完成前使用一个或多个 WaitHandle 对象阻止的应用。使用 AsyncWaitHandle 调用 WaitOne 方法,对单个操作阻止应用。 若要在等待一组异步操作完成期间阻止应用,请将相关的 AsyncWaitHandle 存储到数组,调用 System.Threading.WaitHandle.WaitAll 方法。若要在等待一组异步操作中任一操作完成期间阻止应用,请将相关的 AsyncWaitHandle 对象存储到数组中,并调用 System.Threading.WaitHandle.WaitAny方法。
以下代码示例展示了如何使用 DNS 类中的异步方法,检索用户指定计算机的域名系统信息。
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace AsynchronousOperations
{
public class WaitUntilOperationCompletes
{
public static void Main()
{
string strHostNameOrAddr = "127.0.0.1";
IAsyncResult result = Dns.BeginGetHostEntry(strHostNameOrAddr, null, null);
result.AsyncWaitHandle.WaitOne();
try
{
IPHostEntry host = Dns.EndGetHostEntry(result);
string[] aliases = host.Aliases;
IPAddress[] addresses = host.AddressList;
if (aliases.Length > 0)
{
Console.WriteLine("Aliases");
for (int i = 0; i < aliases.Length; i++)
{
Console.WriteLine("{0}", aliases[i]);
}
}
if (addresses.Length > 0)
{
Console.WriteLine("Addresses");
for (int i = 0; i < addresses.Length; i++)
{
Console.WriteLine("{0}",addresses[i].ToString());
}
}
}
catch (SocketException e)
{
Console.WriteLine("Exception occurred while processing the request: {0}", e.Message);
}
}
}
}
下面的代码示例展示了如何使用 Dns 类中的异步方法,检索用户指定计算机的域名系统信息。
using System;
using System.Net;
using System.Net.Sockets;
namespace AsynchronousOperations
{
public class BlockUntilOperationCompletes
{
public static void Main(string[] args)
{
string strHostNameOrAddr = "127.0.0.1";
IAsyncResult result = Dns.BeginGetHostEntry(strHostNameOrAddr, null, null);
try
{
IPHostEntry host = Dns.EndGetHostEntry(result);
string[] aliases = host.Aliases;
IPAddress[] addresses = host.AddressList;
if (aliases.Length > 0)
{
Console.WriteLine("Aliases");
for (int i = 0; i < aliases.Length; i++)
{
Console.WriteLine("{0}", aliases[i]);
}
}
if (addresses.Length > 0)
{
Console.WriteLine("Addresses");
for (int i = 0; i < addresses.Length; i++)
{
Console.WriteLine("{0}",addresses[i].ToString());
}
}
}
catch (SocketException e)
{
Console.WriteLine("An exception occurred while processing the request: {0}", e.Message);
}
}
}
}
如果应用可以在等待异步操作结果期间继续执行其他工作,不得阻止应用一直到操作完成。 请使用下列方法之一,在应用等待异步操作完成期间继续执行指令:
使用异步操作的 BeginOperationName 方法返回的 IAsyncResult 的 IsCompleted 属性,确定操作是否已完成。
使用 AsyncCallback 委托,在单独的线程中处理异步操作结果。
下面的代码示例展示了如何使用 Dns 类中的异步方法,检索用户指定计算机的域名系统信息。 此示例启动异步操作,然后在控制台打印句点 ("."),直到操作完成。
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace AsynchronousOperations
{
public class PollUntilOperationCompletes
{
static void UpdateUserInterface()
{
Console.Write(".");
}
public static void Main(string[] args)
{
string strHostNameOrAddr = "127.0.0.1";
IAsyncResult result = Dns.BeginGetHostEntry(strHostNameOrAddr, null, null);
while (result.IsCompleted != true)
{
UpdateUserInterface();
}
try
{
IPHostEntry host = Dns.EndGetHostEntry(result);
string[] aliases = host.Aliases;
IPAddress[] addresses = host.AddressList;
if (aliases.Length > 0)
{
Console.WriteLine("Aliases");
for (int i = 0; i < aliases.Length; i++)
{
Console.WriteLine("{0}", aliases[i]);
}
}
if (addresses.Length > 0)
{
Console.WriteLine("Addresses");
for (int i = 0; i < addresses.Length; i++)
{
Console.WriteLine("{0}",addresses[i].ToString());
}
}
}
catch (SocketException e)
{
Console.WriteLine("An exception occurred while processing the request: {0}", e.Message);
}
}
}
}
下面的代码示例展示了如何使用 Dns 类中的异步方法,检索用户指定计算机的域名系统 (DNS) 信息。
using System;
using System.Net;
using System.Net.Sockets;
namespace AsynchronousOperations
{
public class UseDelegateForAsyncCallback
{
public static void Main()
{
string strHostNameOrAddr = "127.0.0.1";
Dns.BeginGetHostEntry(strHostNameOrAddr, new AsyncCallback(ProcessDnsInformation), strHostNameOrAddr);
for (int i = 0; i < 10; i++)
{
Console.WriteLine("...");
}
Console.ReadKey();
}
static void ProcessDnsInformation(IAsyncResult result)
{
string hostName = (string) result.AsyncState;
try
{
IPHostEntry host = Dns.EndGetHostEntry(result);
string[] aliases = host.Aliases;
IPAddress[] addresses = host.AddressList;
if (aliases.Length > 0)
{
Console.WriteLine("Aliases");
for (int j = 0; j < aliases.Length; j++)
{
Console.WriteLine("{0}", aliases[j]);
}
}
if (addresses.Length > 0)
{
Console.WriteLine("Addresses");
for (int k = 0; k < addresses.Length; k++)
{
Console.WriteLine("{0}",addresses[k].ToString());
}
}
}
catch (SocketException e)
{
Console.WriteLine("An exception occurred while processing the request: {0}", e.Message);
}
}
}
}
下面的代码示例展示了如何使用 Dns 类中的异步方法,检索用户指定计算机的域名系统 (DNS) 信息。 此示例定义并使用 HostRequest 类存储状态信息。 HostRequest 对象是针对用户输入的每个计算机名进行创建。 此对象传递给 BeginGetHostByName 方法。 每当请求完成时,都会调用 ProcessDnsInformation 方法。 HostRequest 对象是使用 AsyncState 属性进行检索。 ProcessDnsInformation 方法使用 HostRequest 对象,存储请求返回的 IPHostEntry 或请求抛出的 SocketException。