异步模式所提供的革新之一就是调用方确定特定调用是否应是异步的。对于被调用的对象,没有必要执行附加的编程来用于支持其客户端的异步行为;在该模式中异步委托提供此功能。公共语言运行库处理调用方和被调用的对象视图之间的差异。被调用的对象可以选择显式支持异步行为,这或者是因为它可以比一般结构更为有效地实现异步行为,或者是因为它想只支持其调用方的异步行为。但是,建议这种被调用的对象遵循公开异步操作的异步设计模式。
类型安全是异步模式的另一项革新。尤其对于异步委托,针对 .NET Framework 和公共语言运行库的语言编译器可令映射到规则 Invoke 方法的开始和结束操作(例如,BeginInvoke 和 EndInvoke)的方法签名是类型安全的。这是十分重要的,因为编译器为异步委托将同步调用拆分成开始和结束操作,使其能够只传递有效参数。
在此模式中所蕴含的基本想法如下所示:
调用方确定特定调用是否应是异步的。
对于被调用的对象,没有必要由其客户端执行附加的编程来用于支持异步行为。公共语言运行库结构应该能够处理调用方和被调用的对象视图之间的差异。
被调用的对象可以选择显式支持异步行为,这或者是因为它可以比一般结构更为有效地实现异步行为,或者是因为它想只支持其调用方的异步行为。但是,建议这种被调用的对象遵循公开异步操作的异步设计模式。
编译器为 BeginInvoke 和 EndInvoke 以及异步委托生成类型安全方法签名。
.NET Framework 提供支持异步编程模型所需的服务。此类服务的部分列表示例是:
同步基元,例如监视器和阅读器编写器锁定。
线程和线程池。
同步构造,例如支持等候对象的容器。
向基础结构片(例如 IMessage 对象和线程池)公开。
该模式将一个同步调用拆分成各构成部分:开始操作、结束操作和结果对象。考虑以下示例,在其中可能要用大量时间来完成 Factorize 方法。
public class PrimeFactorizer
{
public bool Factorize(int factorizableNum, ref int primefactor1, ref int primefactor2)
{
// Determine whether factorizableNum is prime.
// If it is prime, return true. Otherwise, return false.
// If it is prime, place factors in primefactor1 and primefactor2.
}
}
如果遵循异步模式,则类库编写器添加 BeginFactorize 和 EndFactorize 方法,这两个方法将同步操作拆分成两个异步操作:
public class PrimeFactorizer
{
public bool Factorize(
int factorizableNum,
ref int primefactor1,
ref int primefactor2)
{
// Determine whether factorizableNum is prime.
// if it is prime, return true; otherwise return false.
// if it is prime, place factors in primefactor1 and primefactor2
}
public IAsyncResult BeginFactorize(
int factorizableNum,
ref int primefactor1,
ref int primefactor2,
AsyncCallback callback,
Object state)
{
// Begin factoring asynchronously, and return a result object,
}
public bool EndFactorize(
ref int primefactor1,
ref int primefactor2,
IAsyncResult asyncResult
)
{
// End (or complete) the factorizing,
// return the results,
// and obtain the prime factors.
}
}
服务器将异步操作拆分成两个逻辑部分:采用来自客户端的输入并调用异步操作的部分,向客户端提供异步操作结果的部分。
除了异步操作所需的输入外,第一部分还采用在完成异步操作时后要被调用的 AsyncCallback 委托。第一部分返回一个可等待的对象,该对象实现客户端使用的 IAsyncResult 接口来确定异步操作的状态。
服务器还使用它返回到客户端的可等待对象来维护与异步操作关联的任何状态。通过提供可等待的对象,客户端使用第二部分获取异步操作的结果。
可用于客户端来启动异步操作的选项有:
在开始异步调用时提供回调委托。
public class Driver1
{
public PrimeFactorizer primeFactorizer;
public void Results(IAsyncResult asyncResult)
{
int primefactor1=0;
int primefactor2=0;
bool prime = primeFactorizer.EndFactorize(
ref primefactor1,
ref primefactor2,
asyncResult);
}
public void Work()
{
int factorizableNum=1000589023,
int primefactor1=0;
int primefactor2=0;
Object state = new Object();
primeFactorizer = new PrimeFactorizer();
AsyncCallback callback = new Callback(this.Results);
IAsyncResult asyncResult = primeFactorizer.BeginFactorize(
factorizableNum,
ref primefactor1,
ref primefactor2,
callback,
state);
}
}
在开始异步调用时不提供回调委托。
public class Driver2
{
public static void Work()
{
int factorizableNum=1000589023,
int primefactor1=0;
int primefactor2=0;
Object state = new Object();
PrimeFactorizer primeFactorizer = new PrimeFactorizer();
AsyncCallback callback = new Callback(this.Results);
IAsyncResult asyncResult = primeFactorizer.BeginFactorize(
factorizableNum,
ref primefactor1,
ref primefactor2,
callback,
state);
bool prime = primeFactorizer.EndFactorize(
ref primefactor1,
ref primefactor2,
asyncResult);
}
} |