Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2920

.pdf
Скачиваний:
1
Добавлен:
15.11.2022
Размер:
2.61 Mб
Скачать

принципе, если вас не интересует, кто записал информацию об ошибке, шаг 2 можно пропустить.

4.Чтобы получить информацию от объекта, вызываются методы IErrorInfo.

Если объект не готов обработать ошибку, а нуждается в передаче информации о ней дальше по цепи вызова, он должен просто возвратить полученный код ошибки. Так как функция GetErrorInfo стирает информацию об ошибке, ассоциированную с потоком, то её должен вызывать только объект, обрабатывающий ошибку.

Вмногоуровневой архитектуре сообщение об ошибке может проходить через большое количество методов различных объектов. Можно вынимать сообщение об ошибке, дописывать его к собственному и закладывать обратно, но со своим кодом ошибки. На практике такая техника выглядит, например, так:

1.В объекте доступа к данным (например, OLE DB) происходит ошибка «нарушение ссылочной целостности».

2.Объект доступа к данным закладывает соответствующее сообщение и возвращает код ошибки. Если это сообщение в неизменном виде дойдет до клиента, тот ни за что не поймет, что же случилось...

3.Промежуточный компонент, управляющий бизнеслогикой, вынимает это сообщение, закладывает сообщение о том, что «Операция добавления данных о клиенте не удалась, так как» и дописывает сообщение, присланное объектом доступа к данным. Далее компонент, управляющий бизнеслогикой, закладывает свой код ошибки и возвращает управление вызвавшему его методу.

4.Пункт три может повторяться до тех пор, пока управление не получит клиентское приложение, инициировавшее всю цепочку вызовов. Клиентское приложение вынимает сообщение и показывает его пользователю.

131

При такой схеме пользователь получит не только сообщение, что произошло «нарушение ссылочной целостности», но и контекст, в котором произошла эта ошибка. Это позволит пользователю более точно понять возникшую ситуацию и правильно отреагировать на нее. Некоторые уровни в этой схеме могут сами интерпретировать происходящую ситуацию и дописывать комментарии, помогающие ее разрешить. В нашем примере таким уточнением может стать предложение проверить правильность введенных атрибутов, имеющих ссылочный тип.

Прямую работу с IErrorInfo можно встретить только в коде, написанном на C/C++. Да и то обычно его пытаются «завернуть» в обработку исключений C++. VB, например, берет на себя обработку COM-ошибок, скрывая от программиста работу с HRESULT и IErrorInfo в специальном объекте «Err».

Прямая обработка ошибок на C++ позволяет создавать более строгий и производительный код, а также дает лучший контроль над процессом обработки ошибок.

2.4.7. Метаданные объектов

Каждый COM-интерфейс, каждый COM-класс и, в принципе, любой элемент COM-библиотеки могут иметь бинарное описание их параметров и атрибутов. Такое описание хранится в библиотеке типов, которая (как уже говорилось) обычно прилинковывается к DLL-модулю или поставляется в отдельном TLB-файле.

Библиотеки типов используются для получения информации об объектах, интерфейсах и пользовательских типах данных. Они также позволяют избавиться от proxy/stub при маршалинге. Создавать библиотеки типов можно с помощью MIDL или программно. VB тоже создает библиотеки типов, но при этом они неразрывно связаны с создаваемыми на

132

нем компонентами. Естественно, VB позволяет использовать библиотеки типов, созданные другими средствами.

Для создания библиотек типов «вручную» используется специальный объект, реализующий интерфейс ICreateTypeLib[2]. Для создания такого объекта используется API-функция CreateTypeLib[2]. Прочитать содержимое библиотеки типов можно с помощью интерфейса ITypeLib. Получить указатель на этот интерфейс можно, вызвав API-

функции LoadTypeLib или LoadRegTypeLib. Для всех интерфейсов, описанных в этом разделе, поддерживается маршалинг, что позволяет получать информацию о типах через сеть.

Disp-интерфейсы (как и dual-интерфейсы) позволяют получить их описание через свой метод IDispatch::GetTypeInfo. На нашем сайте в электронной версии этой статьи можно найти пример, показывающий, как получить информацию о типе содержимого VARIANT’а. Хотя в этом примере речь описывается техника работы с типом VARIANT, часть этого примера можно использовать как общее описание работы с библиотеками типов и интерфейсом ITypeInfo. Там же можно найти и CORBA-аналог этого проекта.

2.4.8. Многопоточность

Многопоточные приложения имеют два основных подводных камня: взаимоблокировки (deadlocks) и гонки (races). Взаимоблокировка происходит, когда один поток ожидает от другого каких-то действий, а тот, в свою очередь, ждет некоторых действий от первого. Состояние гонок возникает, если один поток заканчивает свою работу раньше, чем другой, от которого он зависит. Из-за этого первый поток получает мусор вместо результатов, ибо второй еще не предоставил верных.

COM помогает предотвратить взаимоблокировки вызовов объектов. Существуют и некоторые функции,

133

созданные для предотвращения состояния гонок во внепроцессных серверах. Хотя COM и поддерживает старую модель, предполагающую наличие одного потока на процесс, создание кода, использующего преимущества многопоточности, делает возможным создание более эффективных приложений, давая возможность потоку работать, пока другой поток ожидает завершения длительной операции.

Стоит сказать и том, что многопоточность сама по себе не гарантирует лучшей производительности. Поскольку создание и синхронизация потоков – сложные задачи, использование многопоточности часто порождает проблемы производительности. Несколько потоков следует использовать только в том случае, когда вы твердо знаете, что делаете.

Самый простой путь понять архитектуру потоков, принятую в COM – это представить, что все COM-объекты в процессе разделены на группы, называемые апартаментами (apartments). COM-объекты всегда живут в одном апартаменте, в том смысле, что их методы могут быть легально вызваны только потоком, принадлежащим этому апартаменту. Любой другой поток, желающий вызвать объект, должен делать это через proxy.

Существует два типа апартаментов: однопоточные апартаменты (single-threaded apartments, STA) и многопоточные апартаменты (multi-threaded apartments, MTA).

Однопоточный апартамент (STA) – это апартамент, содержащий только один поток. COM синхронизирует все обращения к методам COM-объекта, находящегося в STA. Делается это через очередь сообщений Windows. Каждый поток клиентского процесса или внепроцессного (EXE) сервера, желающий работать в отдельном апартаменте, должен вызвать CoInitialize или CoInitializeEx с параметром dwCoInit, равным COINIT_APARTMENTTHREADED (эти вызовы и приводят к инициализации потока и выделению ему синхронизирующей очереди сообщений). Внутрипроцессные

134

объекты, располагающиеся в DLL (в том числе COM+/MTSобъекты), регистрируют свою поточную модель в реестре с помощью именованного значения ThreadingModel внутри ключа InprocServer32. При передаче указателей на интерфейсы между разными STA, или между STA и MTA, должен обязательно производиться маршалинг. При передаче указателя на интерфейс как параметра метода какого-нибудь интерфейса, или при создании нового COM-объекта, маршалинг делается автоматически. Если необходимо вручную (без использования COM, например, через общую область памяти) передать указатель на интерфейс другому потоку, необходимо произвести «ручной» маршалинг.

Для «ручного» маршалинга используется функция

CoMarshalInterThreadInterfaceInStream. В качестве первого параметра ей передается IID интерфейса. В качестве второго – указатель на этот интерфейс. В качестве третьего – указатель на интерфейс IStream, в который и будет записана информация о передаваемом интерфейсе. Перед вызовом этой функции необходимо создать объект, реализующий интерфейс IStream. Самый простой способ сделать это – воспользоваться API-

функцией CreateStreamOnHGlobal, создающей Stream,

базирующийся на оперативной памяти. Последнее, что необходимо сделать – это из другого потока выполнить обратный маршалинг. Для этого необходимо вызвать

CoGetInterfaceAndReleaseStream. Ручной маршалинг очень редко применяется на практике. Если же возникнет необходимость делать его часто, то можно создать простой класс-обертку, или воспользоваться глобальной (для процесса) таблицей интерфейсов. Она похожа на AOM (Active Object Map) в Corba. Управление глобальной таблицей интерфейсов производится через стандартный интерфейс IGlobalInterfaceTable. Указатель на него можно получить,

создав COM-объект с CLSID CLSID_StdGlobalInterfaceTable.

Еще один способ избавиться от «ручного маршалинга» – агрегировать специальный объект FreeThreadedMarshaler. Для

135

создания такого объекта используется функция

CoCreateFreeThreadedMarshaler. ATL Wizard позволяет автоматизировать всю работу по созданию и агрегированию

ThreadedMarshaler.

При использовании STA нет необходимости в ручной синхронизации, ведь все вызовы и так происходят строго последовательно.

Процесс может содержать любое количество STA. Многопоточный апартамент (MTA) – это апартамент,

содержащий несколько потоков. MTA еще называют свободно-поточным. Маршалинг указателей на интерфейсы в MTA-апартаменте не производится, а любой компонент может получать вызовы своего метода из любого другого потока, входящего в этот же MTA. При этом вызовы методов компонента могут осуществляться параллельно. Параллелизм многопоточных объектов обеспечивает высочайшую производительность и полностью использует преимущества многопроцессорного аппаратного обеспечения. Он позволяет пользователям работать, не дожидаясь окончания длительных операций, выполняемых другими пользователями. Однако синхронизация, и вообще все, что связано с потокобезопасностью, возлагается на код вызываемого компонента. Для синхронизации при этом можно использовать стандартные средства Windows (Мьютексы, Семафоры, События и, конечно, оконные очереди). Создание корректно работающего многопоточного ПО – задача не из простых. Многопоточная отладка, пожалуй, самая неудобная сторона современного программирования, но получаемые преимущества зачастую перевешивают трудности.

Процесс может содержать только один MTA.

Все процессы имеют апартаментную модель, просто некоторые апартаменты содержат один поток, а некоторые – несколько. Поточная модель применима к апартаменту, а не к процессу. Она также может быть применима к CoClass’у но не к DLL-модулю. Разные классы в одной DLL могут иметь

136

разные модели потоков. Но, все же, ATL позволяет определять так называемую глобальную потоковую модель, влияющую на потоковые характеристики всех входящих в модуль объектов.

Процесс, содержащий два или более STA, и не содержащий MTA, называется процессом с апартаментной моделью (apartment model process).

Процесс с одним потоком является частным случаем STA-модели. Такой процесс называется однопоточным (singlethreaded process).

Процесс, содержащий MTA и один или более STA, называется процессом со смешанной моделью (mixed model process).

Процесс, содержащий MTA и не содержащий STA, называется свободно-поточным процессом (free-threaded process).

Главным апартаментом процесса считается тот, который был первым проинициализирован. В однопоточном процессе он остается единственным.

Модели потоков в COM предоставляют механизм совместной работы клиентов и серверов, использующие различные архитектуры потоков. Поддерживаются вызовы между объектами с разными моделями потоков как в разных процессах, так и внутри одного. С точки зрения вызывающего объекта все вызовы объектов вне процесса выглядят одинаково, неважно, какие потоки использует вызываемый объект, и наоборот.

В СОМ не существует аналогичной CORBA сессионной идеологии работы с потоками, когда все вызовы от одного клиента выполняются в одном потоке, а другого – в другом. Но если каждый клиент будет создавать отдельную копию STA-компонента, то внешне это будет похоже на сессионный метод CORBA. Единственное отличие заключается в том, что если двум таким компонентам взбредет в голову обратиться друг к другу, или к общему STA-компоненту, то в COM эти методы будут автоматически синхронизированы.

137

Выбор поточной модели для объекта зависит от назначения этого объекта. Объекту, управляющему некоторым общим ресурсом, (объекту, к которому производятся частые параллельные обращения), лучше поддерживать многопоточность. Это обеспечит максимальную эффективность при обслуживании клиентов. С другой стороны, объект, взаимодействующий с одним пользователем, может поддерживать STA для синхронизации вызовов.

Межпроцессная и межпоточная модели похожи. Если нужно передать указатель на интерфейс объекту в другом апартаменте (или потоке) в этом же процессе, используется такая же модель маршалинга, что и для объектов в разных процессах. С помощью указателя на стандартный объект маршалинга можно произвести маршалинг указателей на интерфейсы через границы потока (апартамента) так же, как и между процессами.

На сегодня большинство языков программирования позволяют создавать COM-объекты в STA-архитектуре, но только C++ позволяет создавать многопоточные компоненты. Библиотека ATL позволяют существенно облегчить эту непростую задачу. Скоро должна появиться седьмая версия VB. Разработчики обещают ввести в эту версию поддержку режима свободных потоков.

138

3.ЛАБОРАТОРНЫЙ ПРАКТИКУМ

3.1.Лабораторная работа № 1

Разработка диаграммы кооперации

1. ОБЩЕЕ ОПИСАНИЕ РАБОТЫ

1.1.Цель работы: разработать диаграмму кооперации в среде Rational Rose и изучить свойства ее элементов.

1.2.Содержание работы

Лабораторная работа заключается в построении диаграммы кооперации.

1.3. Используемое оборудование

Для выполнения лабораторной работы используется ПЭВМ типа IBM PC, Монитор с графическим адаптером VGA

ивыше.

2.ВЫПОЛНЕНИЕ РАБОТЫ

2.1.Особенности разработки диаграмм кооперации

всреде IBM Rational Rose. Активизировать рабочее окно диаграммы кооперации в программе IBM Rational Rose 2003 можно несколькими способами:

щелкнуть на кнопке с изображением диаграммы

взаимодействия настандартной

панели

инструментов и

выбрать для построения новую диаграмму кооперации;

выполнить

операцию

главного

меню: Browse Interaction Diagram (Браузер Диаграмма взаимодействия) и выбрать для построения новую диаграмму кооперации;

выполнить

операцию

контекстного

меню: New Collaboration

 

 

Diagram (Новая Диаграмма кооперации)

для логического

 

139

 

представления или представления вариантов использования в браузере проекта.

При этом появляется новое окно с чистым рабочим листом диаграммы кооперации и специальная панель инструментов, содержащая кнопки с изображением графических примитивов, необходимых для разработки

диаграммы кооперации (табл.

3.1). Назначение отдельных

кнопок панели можно узнать из всплывающих подсказок.

 

 

Таблица 3.1

Назначение кнопок специальной панели инструментов

 

диаграммы кооперации

Графическое

Всплывающа

Назначение кнопки

изображение

я подсказка

 

 

Selection Tool

Превращает изображение

 

 

курсора в форму стрелки для

 

 

последующего выделения

 

 

элементов на диаграмме

 

Text Box

Добавляет на диаграмму

 

 

текстовую область

 

 

 

 

Note

Добавляет на диаграмму

 

 

примечание

 

 

 

 

Anchor Note

Добавляет на

 

to Item

диаграмму связь примечания с

 

 

соответствующим

 

 

графическим элементом

 

 

диаграммы

 

Object

Добавляет на

 

 

диаграмму объект

 

 

 

 

Class Instance

Добавляет на диаграмму

 

 

экземпляр класса

 

Object Link

Добавляет на

 

 

диаграмму связь

140

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]