Выбрать главу

using System;

using System.Threading;

using System.Runtime.Remoting;

public class Server {

     public static bool Sum(int x, int y, out int z) {

          Console.WriteLine(

               "Server (Sum method) thread = " +

              Thread.CurrentThread.GetHashCode()+

              "; PoolThread = "+

              Thread.CurrentThread.IsThreadPoolThread);

          Thread.Sleep(1000);

          z = 0;

          try {

               z = checked((int)(x + y));

          }

          catch (Exception) {

               return false;

           }

           return true;

      }

      public static bool MultBy2(int x, out int y) {

            Console.WriteLine {

                   "Server (MultBy2 method) thread = " +

                   Thread.CurrentThread.GetHasheode()+

                    "; PoolThread = "+

                    Thread.CurrentThread.IsThreadPoolThread);

       Thread.Sleep(1000);

        y = 0;

        try {

             у = checked((int) (x*2));

        }

        catch (Exception) {

             return false;

         }

         return true;

     }

}

Public class Client {

       private static int workCount = 0;

       private delegate bool HardFunction2Args (

            int x, int y, out int result);

       private delegate bool HardFunctionlArg (

            int x, out int result);

       private static void SumCallback(IAsyncResult ar) {

             int z;

             HardFunction2Args sum =

                (HardFunction2Args)ar.AsyncState;

             bool result = sum.Endlnvoke(out z, ar);

             if (result) Console.WriteLine (

                  "SumCallback: Sum = " + z);

             else Console.WriteLine (

                  "SumCallback: Bad arguments for Server.Sum

             workCount++;

        }

        private static void MultCallback(IAsyncResult ar) {

             int z;

             HardFunctionlArg mult =

                   (HardFunctionlArg)ar.AsyncState;

             bool result = mult.Endlnvoke(out z, ar);

             if (result) Console.WriteLine (

                  "MultCallback: MultBy2 = " + z);

             else Console.WriteLine (

                  "MultCallback: Bad argument for MultBy2");

              workCount++;

        }

        public static void Main() {

             int sumResult, multResult, count = 0;

             Console.WriteLine("Client thread = " +

                    Thread.CurrentThread.GetHashCode() + PoolThread = "+

                    Thread.CurrentThread.IsThreadPoolThread);

              HardFunction2Args sum =

                     new HardFunction2Args(Server.Sum);

              HardFunctionlArg mult =

                     new HardFunctionlArg(Server.MultBy2);

              AsyncCallback sumCallback =

                     new AsyncCallback(SumCallback);

              AsyncCallback multCallback =

                     new AsyncCallback(MultCallback);

              IAsyncResult arSum = sum.Beginlnvoke(3, 4,

                     out sumResult, sumCallback, sum);

               IAsyncResult arMult = mult.Beginlnvoke(5,

                      out multResult, multCallback, mult);

               while (workCount < 2) {

                       Console.WriteLine("Client thread: count = "+ count++);

                       Thread.Sleep(100);

              }

              Console.WriteLine("Bye!");

        }

}

Комментарии к коду.

Сервер и клиент представлены соответственно классами Server и Client.

Сервер

Сервер реализует два статических метода:

• Метод public static bool Sum(int x, int у, out int z) {… } обеспечивает сложение двух чисел типа int. Результат записывается в переменную z типа int. В случае возникновения переполнения возвращается false, при его отсутствии — true.

Временная сложность проводимых вычислений имитируется с помощью вызова Thread.Sleер(1000).

В самом начале, еще до проведения вычислений, на консоль выводится хеш потока, выполняющего вызов (Thread.CurrentThread.GetHashCode()), и информация о принадлежности данного потока классу рабочих потоков из пула потоков (Thread.CurrentThread.IsThreadPoolThread)).

• Метод public static bool MuitBy2(int x, out int y) {… } обеспечивает умножение числа на 2 и реализован аналогично предыдущему методу.

Здесь важно отметить, что разработчик сервера не заботится о том, как именно будут вызываться методы сервера клиентами — синхронно или асинхронно. Все зависит от клиента. Он может вызывать методы сервера как синхронно, так и асинхронно.

Клиент. Типы используемых делегатов

В данном примере клиент вызывает методы сервера асинхронно, что достигается за счет использования делегатов.

В коде клиента используются делегаты трех типов:

• HardFunction2Args

Этот тип определяется в классе client:

private delegate bool HardFunction2Args (int x, int y, out int result);

Данный делегат может делегировать вызов (как синхронный так и асинхронный) любому методу (как статическому так и нестатическому) любого класса с заданной сигнатурой (два входных параметра типа int, один выходной типа int, возвращаемое значение типа bool). В нашем случае вызов будет делегироваться методу Server::Sum.

• HardFunctionlArg

Этот тип также определяется в классе Client:

private delegate bool HardFunctionlArg (int x, out int result);

Данный делегат может делегировать вызов (как синхронный так и асинхронный) любому методу (как статическому так и нестатическому) любого класса с заданной сигнатурой (один входной параметр типа int, один выходной типа int, возвращаемое значение типа bool). В данном случае вызов будет делегироваться методу Server::MultBy2.

 AsyncCallback

Этот тип определен в System. Он может использоваться для делегирования вызова методу со следующей сигнатурой:

♦ один входной параметр типа IAsyncResult (тип определен в System);

♦ возвращаемое значение отсутствует (void).

В нашем случае делегаты данного типа будут использоваться для делегирования вызовов методам клиента Client::SumCallback и Client::MultCallback.

Метод

private static void SumCallback (IAsyncResult ar) {… }

клиента вызывается инфраструктурой асинхронных вызовов для уведомления клиента о том, что сделанный им ранее асинхронный вызов метода sum сервера завершен.

Аналогично, метод

private static void MultCallback (IAsyncResult ar) {… }

клиента вызывается инфраструктурой асинхронных вызовов для уведомления клиента о том, что сделанный им ранее асинхронный вызов метода MuitBy2 сервера завершен также.

Клиент. Инициирование асинхронных вызовов

Прежде чем обсуждать завершение асинхронных вызовов уместно рассмотреть их инициирование. Для этого обратимся к коду метода Client::Main.

Прежде всего клиент выводит на консоль хеш основного потока

(Thread. CurrentThread. GetHashCode()) и информацию о принадлежности данного потока классу рабочих потоков из пула потоков

(Thread.CurrentThread.IsThreadPoolThread)).

Далее создаются два делегата для инициирования асинхронных вызовов методов сервера. Делегат sum

HardFunction2Args sum = new HardFunction2Args(Server.Sum);

используется для асинхронного вызова метода Server::Sum, а делегат mult

HardFunctionlArg mult = new HardFunctionlArg(Server.MultBy2);

используется для асинхронного вызова метода Server::MultBy2.

Далее формируются делегаты sumCallback и multCallback