Как не трудно заметить, в текущем примере метод Main() не помещает возвращаемый Beginlnvoke () тип IAsyncResult в кэш и больше не вызывает метод Endlnvoke ().
Объясняется это тем, что у целевого метода делегата AsyncCallback (каковым в данном
примере является метод AddComplete()) нет доступа к исходному делегату BinaryOp,
создаваемому в Main(). И хотя можно было бы просто объявить переменную BinaryOp
статической переменной класса, чтобы позволить обоим методам получать доступ к
одному и тому же объекту, более элегантное решение связано с применением входного
параметра IAsyncResult.
Любой входной параметр IAsyncResult, передаваемый целевому методу делегата
AsyncCallback, на самом деле представляет собой экземпляр класса AsyncResult
(обратите внимание на отсутствие префикса I), определенного в пространстве имен System.Runtime.Remoting.Messaging. Статическое свойство AsyncDelegate возвращает
ссылку на исходный асинхронный делегат, который был создан в другом месте программы.
Значит, если необходимо получить ссылку на объект делегата BinaryOp, находящийся
в Main(), достаточно просто привести возвращаемый свойством AsyncDelegate тип
System.Object к типу BinaryOp. После этого, как и следовало ожидать, можно
вызывать метод Endlnvoke():
// Здесь нужно не забыть импортировать пространство имен
// System.Runtime.Remoting.Messaging!
static void AddComplete(IAsyncResult itfAR)
{
Console.WriteLine("AddComplete() invoked on thread {0}.",
Thread.CurrentThread. ManagedThreadId);
Console.WriteLine("Your addition is complete"); // сложение выполнено
// Теперь получить результат.
AsyncResult ar = (AsyncResult)itfAR;
BinaryOp b = (BinaryOp)ar.AsyncDelegate;
Console.WriteLine ("10 + 10 is {0}.", b.EndInvoke(itfAR));
}