Интернет-журнал "Домашняя лаборатория", 2007 №6
Шрифт:
Эксперименты
Эксперименты с вышеописанным кодом должны продемонстрировать работу сервисов синхронизации и трассировки вызовов.
Все компоненты размещаются в одном контексте
Первый эксперимент не требует какой-либо модификации кода клиента и сервера. Каждому компоненту (Account, Tax, News) приписаны два атрибута:
[Synchronization ]
[MyCallTrace("LogFile")]
Таким
Запустив серверное приложение и параллельно два клиентские приложения, мы увидим на консоли сервера информацию о том, что все три компонента выполняются в контексте 1.
Ниже приведены несколько первых строк с консоли сервера
Server is listening
News context = 1 News constructor thread = 3 IsPoolThread = True
Tax context = 1 Tax constructor thread = 3 IsPoolThread = True
Account context = 1 Account constructor thread = 3 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
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
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 {
HttpChannel с = new HttpChannel;
ChannelServices.RegisterChannel(c);
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.