异步机制的要求
为了能够最充分地利用.NET异步调用的能力,就必须首先了解对于现代面向组件的异步调用支持的普遍要求:
1.同一组件代码应当都可以用于异步和同步调用。这样就允许组件开发者专注于业务逻辑和有助于使用一致的标准机制。
2.第一个要求的一个推论是应当由客户端代码来决定是否使用异步或同步方式来调用代码·。因此,客户端代码就得拥有不同的代码来进行同步和异步调用。
3.客户端代码应当能够发起多个异步调用和执行多个异步调用。并且能够辨别多个目标方法的完成。
4.同理,组件应当提供多种并行调用的方式。
5.如果组件方法存在输出参数或返回值,当控制权返回给客户端时这些参数或值对于客户端代码是不可用的。当方法完成时,客户端代码应当通过一种方式来访问它们。
6.同样,在组件端上的错误也应当传达给客户端代码。在方法执行期间抛出的任何异常应当随后发回客户端代码。
7.异步调用机制应当简单直接地使用。例如,该机制应当隐藏其实现细节——如用来调度调用的工作线程等等。
当客户端代码发送一个异步方法调用时,应当有如下选择:
1.在方法执行期间进行一些工作,直到方法完成时阻断。
2.在方法执行期间进行一些工作,然后轮询完成状态。
3.在方法执行期间进行一些工作,等待一个预定的时间量后停止等待,即使该方法尚未完成执行。
4.同时等待多个方法的完成。客户端代码可以选择等待所有或是任何挂起的调用的完成。
5.当方法完成时接收通知。通知的形式是客户端代码提供的方法的一个回调。该回调应当包含信息来标识是哪个方法已完成以及方法的返回值。
重访委托
对于编程者来说,一个委托就是一个类型安全的方法引用。用来委托从客户端代码到委托类调用方法的指令。例如,一个Calculator类:
public class Calculator
{
public int Add(int argument1, int argument2)
{
return argument1 + argument2;
}
public int Subtract(int argument1, int argument2)
{
return argument1 - argument2;
}
//其他方法
}
可以定义一个称为BinaryOperation委托,来取代直接调用Add()方法,并使用BinaryOperation来调用方法:
public delegate int BinaryOperation(int argument1, int argument2);
Calculator calculator = new Calculator();
BinaryOperation oppDel = calculator.Add;
int result = 0;
result = oppDel(2, 3);
Debug.Assert(result == 5);
默认情况下,当使用委托来调用方法的时候,委托会阻断调用者直到所有目标方法返回。在上面例子中,调用者会一直被阻断直到Add()返回。但是,委托同样可以用于异步调用其目标方法。事实上委托不存在任何特别的地方,因为委托实际上是编译成类的。当定义一个委托类型时,编译器会转换委托定义到一个成熟的,特定标记的类定义,并插入该类以取代委托定义。例如,对于如下委托定义:
public delegate int BinaryOperation(int argument1, int argument2);
编译器会生成这样的类定义:
public sealed class BinaryOperation : MulticastDelegate
{
public BinaryOperation(object target, int methodPtr)
{...}
public virtual int Invoke(int argument1, int argument2)
{...}
public virtual IAsyncResult BeginInvoke(int argument1, int argument2, AsyncCallback callback, object asyncState)
{...}
public virtual int EndInvoke(IAsyncResult result)
{...}
}
当直接使用委托来调用方法时,如下面的代码:
Calculator calculator = new Calculator();
BinaryOperation oppDel = calculator.Add;
oppDel(2, 3);
编译器会转换对于oppDel(2,3)的调用到对于Invoke()方法的调用。Invoke()方法会阻断调用者,并在调用者线程中执行方法,然后返回控制权给调用者。编译器生成的BinaryOperation类继承于MulticastDelegate类,该类定义在System命名空间下。MulticastDelegate类提供了每个委托都具有的内部委托列表的实现,并且该类也继承于抽象类Delegate。编译器同样会定义两个方法用来管理异步方法调用,它们是BeginInvoke()和EndInvoke()。