Добавить в цитаты Настройки чтения

Страница 222 из 372

Account Add thread = 65 IsPoolThread = True

Tax notification: new Account operation: +5

Tax Notify thread = 3 IsPoolThread = True

News notification: new Account operation: +5

News Notify thread = 3 IsPoolThread = True

News notification: direct notification from Account

News Notify thread = 3 IsPoolThread = True

Account Add thread = 3 IsPoolThread = True

…….

Еще одно замечание, связанное с консолью сервера — конструкторы компонентов выполняются в одном рабочем потоке, а далее эти компоненты вызываются двумя рабочими потоками. Эти потоки, конечно, никак не связаны с клиентами. Можно модифицировать код клиента и сервера, передавая при вызове метода Add не только сумму вклада, но и идентификатор процесса, в котором исполняется клиент, сделавший вызов. После этого можно заметить, что оба рабочих потока выполняют вызовы клиентов не зависимо от процесса клиента. Да и число рабочих потоков не связано напрямую с числом клиентов.

Модификация кода сервера (MyServer.cs) связана с добавлением интерфейса IAccumuiatorNew:

……

namespace SPbU.AOP_NET {

public interface IAccumuiatorNew{

       void Add(int sum, int clientProcessId);

}

……

public class Account: ContextBoundObject, IAccumulator,

       IAudit, IAccumuiatorNew!

……

       public void Add(int sum, int clientProcessId){

           _sum += sum;

           _tax.Notify("new Account operation: +" + sum);

           _tax.news.Notify("direct notification from Account");

           Console.WriteLine("Account Add thread = " +

                Thread.CurrentThread.GetHasheode() +

                " IsPoolThread = " +

               Thread.CurrentThread.IsThreadPoolThread +

               " clientProcessId ="+ clientProcessId);

       }

……

Необходимая модификация клиента (MуАрр. cs) представлена ниже

…….

using System.Diagnostics;

public class MyApp {

    public static void Main() {

           HttpCha

           Cha

           Process p = Process.GetCurrentProcess();

           try {

……

                for (int i=0; i<100; i++) {

                   a. Add(5, p.Id);

              }

…….

       }

…….

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

Account Add thread = 65 IsPoolThread = True clientProcessId =192

Tax notification: new Account operation: +5

Tax Notify thread = 65 IsPoolThread = True

News notification: new Account operation: +5

News Notify thread = 65 IsPoolThread = True

News notification: direct notification from Account

News Notify thread = 65 IsPoolThread = True

Account Add thread = 65 IsPoolThread = True clientProcessId =192

Tax notification: new Account operation: +5

Tax Notify thread = 3 IsPoolThread = True

News notification: new Account operation: +5

News Notify thread = 3 IsPoolThread = True

News notification: direct notification from Account

News Notify thread = 3 IsPoolThread = True

Account Add thread = 3 IsPoolThread = True clientProcessId =165

Tax notification: new Account operation: +5

Tax Notify thread = 3 IsPoolThread = True

News notification: new Account operation: +5

News Notify thread = 3 IsPoolThread = True

News notification: direct notification from Account

News Notify thread = 3 IsPoolThread = True

…….





Еще стоит обратить внимание на то, что рабочий поток, выполняющий вызов метода Add компонента Account, выполняет и вызовы метода Notify для компонентов Tах и News, инициированные из компонента Account. Причина в том, что в рамках данного эксперимента все три компонента находятся в одном контексте синхронизации, и поток, вошедший в этот контекст, не выходит из него, пока не будут сделаны все вышеупомянутые вызовы. Только после этого другой поток может войти в данный контекст и начать выполнение метода Add.

Просмотрев файл LogFile, в который выполняется запись данных о перехваченных вызовах, можно заметить, что трассируются только вызовы к компоненту Account. Это объясняется тем, что именно компонент Account получает вызовы извне контекста (от клиентов), и эти вызовы перехватываются перехватчиком входящих вызовов атрибута трассировки. Вызовы, которые делаются к компонентам Tах и News, идут от компонентов Account и Tах и не пересекают границу контекста. Именно поэтому они и не перехватываются. Первые строки файла LogFile представлены ниже:

===SPbU.AOP_NET.Account, MyServer, Version=0.0.0.0,

     Culture=neutral, PublicKeyToken=null

ctor

      <<<IN>>> parameters: (

}

===SPbU.AOP_NET.Account, MyServer, Version=0.0.0.0,

     Culture=neutral, PublicKeyToken=null

ctor

      <<<OUT>>> parameters: {

}

===System.MarshalByRefObject, mscorlib, Version=1.0.3300.0,

     Culture=neutral, PublicKeyToken=b77a5c561934e089

InitializeLifetimeservice

      <<<IN>>> parameters: (

}

===System.MarshalByRefObject, mscorlib, Version=1.0.3300.0,

    Culture=neutral, PublicKeyToken=b77a5c561934e089

InitializeLifetimeservice

         <<<OUT>>> parameters: (

}

===clr: SPbU.AOP_NET.Account, MyServer

Add

      <<<IN>>> parameters: {

sum= 5

'

clientProcessId= 192)

===clr: SPbU.AOP_NET.Account, MyServer

Add

       <<<IN>>> parameters: {

sum= 5

'

clientProcessId= 165)

===clr: SPbU.AOP_NET.Account, MyServer

Add

        <<<OUT>>> parameters: {

}

===clr: SPbU.AOP_NET.Account, MyServer

Add

       <<<OUT>>> parameters: {

}

===clr: SPbU.AOP_NET.Account, MyServer

Add

        <<<IN>>> parameters: {

sum= 5

'

clientProcessId= 192)

===clr: SPbU.AOP_NET.Account, MyServer

Add

         <<<OUT>>> parameters: {

}

Компоненты размещаются в двух контекстах, но в одном домене синхронизации

Закомментируем атрибут Synchronization (), приписанный классу Account. Теперь, просматривая вывод на консоль сервера, можно заметить, что компонент Account размещается в контексте 1, а компоненты Tax и News в контексте 2:

Server is listening

News context = 2 News constructor thread = 9 IsPoolThread = True

Tax context = 2 Tax constructor thread = 9 IsPoolThread = True

Account context = 1 Account constructor thread = 9 IsPoolThread = True

…….

Просматривая файл LogFile видим, что теперь перехватываются вызовы к компонентам Tax и News, поступающие от компонента Account:

===SPbU.AOP_NET.Tax, MyServer, Version=0.0.0.0,

    Culture=neutral, PublicKeyToken=null

ctor

      <<<IN>> parameters: {

}

===SPbU.AOP_NET.Tax, MyServer, Version=0.0.0.0,

     Culture=neutral, PublicKeyToken=null

ctor

      <<<OUT>>> parameters: {

}

===SPbU.AOP_NET.Tax, MyServer, Version=0.0.0.0,