COM+ и .NET – практический подход – часть 3 - Как уведомить ASP.NET из серверного приложения COM+
ОГЛАВЛЕНИЕ
Как уведомить ASP.NET из серверного приложения COM+
Регистрация класса в качестве серверного приложения COM+ повышает устойчивость и доступность приложения, но имеет недостатки. Один недостаток – необходимость использовать дистанционную связь между компонентом COM+ и вызывающим приложением. Если вызывается компонент COM+ - дистанционная связь осуществляется CLR, но если надо вызвать приложение из приложения COM+, для ее обеспечения придется сделать некоторую работу.
Один из распространенных сценариев – события обратного вызова из приложения COM+ к вызывающему приложению. Когда приложению COM+ надо вызвать приложение, приложение превращается в сервер дистанционной связи. Чтобы приложение служило сервером дистанционной связи, ему надо назначить порт TCP.
Пора посмотреть, как реальная задача решается с помощью серверных приложений COM+ и событий обратного вызова. Допустим, надо прочитать из базы данных очень большой объем данных, обработать эти данные и отобразить все данные пользователю. При стандартной схеме обработки страницы извлекаются все данные, форматируются и отправляются клиенту в одном буфере. Конечный пользователь получит очень медленное приложение. При работе с большим объемом данных лучше прочитать кусок от всех данных, отформатировать его и отправить непосредственно пользователю. Применение такой схемы дает ощущение использования хорошо работающей системы. Пользователь быстро видит какие-то данные, и по мере увеличения времени он видит все больше данных, пока не отправятся все данные.
Для обеспечения такой последовательности обработки страницы необходимо: а) установить буферизацию в ложь, чтобы можно было отправлять куски данных; б) прочитать данные из базы данных с помощью DataReader, собрать кусок записей, отформатировать его и отправить клиенту. Для повышения устойчивости приложения лучше поместить чтение данных в класс, регистрирующийся как приложение COM+. Чтобы компоненты COM+ могли отправлять куски данных приложению, реализуются события обратного вызова, уведомляющие вызывающую программу, когда кусок данных готов к форматированию и отправке.
Пробный проект состоит из нового веб-приложения (ASPNET_COMPLUSE_CALLBACK), обычной сборки (ComPlusFacade) и класса серверного приложения COM+ (ComPlusLib). Задача ComPlusFacade – получить события компонента COM+ и записать полученные данные в выходной буфер. ComPlusFacade является отдельной сборкой, потому что и вызывающее приложение, и вызываемый компонент COM+ должны быть в GAC(глобальный кэш сборок), чтобы позволить абсолютно всем им использовать другого. Перед запуском примера не забудьте зарегистрировать эти сборки в GAC.
ComPlusLib содержит два класса: XMLArg, декорированный атрибутом Serializable, чтобы обеспечить передачу аргумента события по каналу дистанционной связи.
[Serializable()]
public class XMLArg : EventArgs
{
string XMLBuffer;
public XMLArg()
{
}
public XMLArg(string XMLBufferArg)
{
this.XMLBuffer = XMLBufferArg;
}
public string XMLBufferArg
{
get
{
return this.XMLBuffer;
}
set
{
this.XMLBuffer = value;
}
}
public override string ToString()
{
return this.XMLBuffer;
}
}
clsComPlusLib является типичным компонентом COM+, содержащим объявленное событие, запускающим каждый сквозной оператор цикла for внутри метода ProcessData.
[ProgId("clsComPlusLib"),
Transaction(TransactionOption.NotSupported),
MustRunInClientContextAttribute(false),
EventTrackingEnabledAttribute(true),
JustInTimeActivation(true),
Synchronization(SynchronizationOption.Required),
Serializable
]
public class clsComPlusLib : ServicedComponent
{
public new event EventHandler DataArrive;
public clsComPlusLib()
{
}
public void ProcessData()
{
for (int i=0 ; i<100000 ; i++)
{
EventArgs XML = new XMLArg ("i=" + i + "<br>\n");
this.DataArrive(null,XML);
}
}
}
CLR зарегистрирует ComPlusLib в COM+. Вы должны зарегистрировать ComPlusLib в GAC посредством перетаскивания или gacutil.exe.
ComPlusFacade – интересная часть примера. ComPlusFacade является связующим звеном между веб-приложением и серверным приложением COM+. FacadeObjByRef также декорирован сериализацией для обеспечения передачи класса через дистанционную связь. Чтобы FacadeObjByRef мог служить сервером дистанционной связи, он унаследован от MarshalByRefObject, и объявлен член типа TcpChannel.
[Serializable()]
public class FacadeObjByRef : MarshalByRefObject
{
protected ComPlusLib.clsComPlusLib eventHandler =
new ComPlusLib.clsComPlusLib();
protected System.IO.Stream outStream;
public static TcpChannel theChannel;
Подрядчик класса получает поток в качестве параметра. Поток отправки должен быть потоком вывода ответа страницы, используемым для выдачи полученных данных клиенту. Внутри конструктора регистрируется TcpChannel, чтобы позволить среде выполнения дистанционной связи выбрать свободный порт и установить обработчик события для события компонента COM+.
public FacadeObjByRef(System.IO.Stream outStream)
{
lock(this)
{
if (theChannel == null)
{
theChannel = new TcpChannel(0);
ChannelServices.RegisterChannel(theChannel);
}
}
if (textEncoder == null)
{
textEncoder = Encoding.UTF8;
}
this.outStream = outStream;
this.eventHandler.DataArrive += new
System.EventHandler(this.DataArive);
}
ProcessData является открытым методом класса, вызываемым веб-страницей и вызывающим приложение COM+ синхронно, чтобы запустить его работу.
public void proccessData()
{
eventHandler.ProcessData();
this.CloseStream();
this.cleanUp();
}
Пока приложение COM+ делает свою работу, событие возбуждается и обрабатывается DataArrive. DataArrive преобразует аргумент события в массив байтов и отправляет этот массив байтов клиенту с помощью внутреннего члена, хранящего буфер потока ответа вызывающей страницы.
public void DataArive(object sender, System.EventArgs e)
{
byte[] toWrite = textEncoder.
GetBytes(((ComPlusLib.XMLArg)e).XMLBufferArg + "\n");
outStream.Write(toWrite, 0, toWrite.Length);
}
ComPlusFacade выполняется в процессе веб-приложения, надо только зарегистрировать его в GAC.
Веб-приложение ASPNET_COMPLUSE_CALLBACK имеет одну страницу aspx (webform1.aspx), отключающую стандартную буферизацию и создающую объект из класса FacadeObjByRef и вызывающую метод ProcessData.
private void Page_Load(object sender, System.EventArgs e)
{
Response.BufferOutput = false;
ComPlusFacade.FacadeObjByRef oObj = new
ComPlusFacade.FacadeObjByRef (Response.OutputStream );
oObj.proccessData ();
}
Осталось запустить ASPNET_COMPLUSE_CALLBACK и посмотреть на его поведение. Страница быстро показывает куски данных, продолжающие приходить, и присоединяет их к HTML в браузере.
Заключение
Цель статьи – показать, как использовать службы COM+ для решения типичных задач программирования при разработке веб-приложений. Начинается с изучения влияния приложения сервера и библиотеки COM+ на производительность и недостатков использования серверного приложения.
После рассмотрения влияния на производительность объясняется и показывается, насколько огромен вклад использования серверного приложения COM+ в устойчивость, надежность приложений и контроль над ними. Решение повседневных задач, таких как инициализация длинного компонента, задача длинных компонентов, уведомление и другие, показывает, как использование служб COM+ и особенно серверных служб COM+ сокращает написание кода и усилия программистов.
COM+ предоставляет мощные службы, помогающие быстро создать развитое и устойчивое приложение. Основной недостаток использования служб COM+ - снижение производительности. Можно использовать часть служб COM+ с помощью служб без компонентов без снижения производительности и приложения библиотеки COM+ с приемлемым снижением. Сервер COM+, предоставляющий наиболее интересные службы, плохо влияет на производительность преимущественно из-за использования DCOM (распределённая компонентная модель объектов).
Перед использованием служб COM+ следует создать пробное приложение и протестировать его с ACT, чтобы выяснить, соответствует ли использование сервера COM+ целевой производительности приложения. Будем надеяться, следующие версии windows, такие как лонгхорн, будут поставляться со службами COM+, не основанными на DCOM, что позволит большему числу приложений использовать серверное приложение COM+.