Проектирование и разработка подсистемы управления транзакциями для АСУД "ЕВФРАТ"

Механизмы управления транзакциями в СУБД. Обзор средств удаленного взаимодействия с объектами. Разработка подсистемы управления транзакциями. Практический анализ производительности подсистемы. Способы защиты пользователей от опасных и вредных факторов.

Рубрика Программирование, компьютеры и кибернетика
Вид дипломная работа
Язык русский
Дата добавления 14.03.2013
Размер файла 449,9 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Наконец, рассмотрим, что из себя представляет TransactionFile. Класс описывает файл, созданный или полученный в результате транзакции. Возможны два варианта: файл не существует, тогда он создается, в него что-то записывается и сохраняется, а при завершении транзакции файл удаляется, или файл существует и модифицируется во время транзакции, а при ее фиксации все изменения в файле фиксируются так же. В конструктор TransactionFile передается строка, определяющая полное имя файла; в конструкторе файлу присваивается уникальный строковый идентификатор, который затем доступен через свойство id. Полное имя файла доступно через свойство FullPath. Свойство transaction возвращает объект транзакции, которая работает с данным файлом. Метод GetStream() по заданному типу доступа возвращает файловый поток. Метод Flush() применяет к файлу все изменения.

2.3.4 Практический анализ производительности подсистемы

С целью исследования производительности полученной подсистемы была реализована тестирующая процедура, имитирующая типичную последовательность действий при использовании системы и использующая подсистему управления транзакциями, а затем осуществлена проверка ее работы на трех различных тестовых конфигурациях. Для сравнения аналогичная процедура была реализована для старой версии АСУД «ЕВФРАТ», не использующей подсистему и таким же образом опробована на трех конфигурациях. Конфигурации стендов приведены в таблице 2.1:

Таблица 2.1. Конфигурация использованных стендов

Процессор

Тактовая частота

Объем оперативной памяти

Тип оперативной памяти

Операционная система

1

Intel Core 2 Quad Q9450

2.66 ГГц

2 ГБ

DDR2

Windows XP Professional

2

Intel Core 2 Duo E8200

2.66 ГГц

2ГБ

DDR2

Windows XP Professional

3

Intel Pentium 4 HT

2.4 ГГц

2 ГБ

DDR2

Windows XP Professional

Было произведено измерение количества выполненных тестов за фиксированный интервал времени - одну минуту. На каждом из перечисленных стендов подсистема управления транзакциями инициализировалась с количеством используемых рабочих потоков от 1 до 8, измерения производились для каждого из этих значений. Кроме этого, на каждом из стендов измерено количество тестов процедуры для старой версии. В результате были получены следующие результаты (в диаграммах для каждого случая приведены три значения - минимальное, среднее и максимальное количество выполнившихся тестов с использованием подсистемы, а так же результаты старой версии - отмечены уровнем затеняющего экрана):

Рисунок 2.1 - Зависимость количества выполненных тестов от числа потоков на 3 стенде

Рисунок 2.2 - Зависимость количества выполненных тестов от числа потоков на 2 стенде

Рисунок 2.3 - Зависимость количества выполненных тестов от числа потоков на 1 стенде

2.3.5 Рекомендации по использованию

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

Другая рекомендация касается улучшения читаемости программного кода. Для выполнения заданий в транзакции созданы методы Invoke() и InvokeAsync(), в которые в качестве указателя на метод удобно передавать так называемое лямбда-выражение - сокращенное объявление анонимного метода, ставшее возможным в C# 3.0. Типичный пример использования методов выглядит следующим образом:

Transaction t = server.OpenTransaction(); //Создание транзакции

//Асинхронное выполнение

t.InvokeAsync(new Func<int>(() =>

{

//Список операторов

}));

//Синхронное выполнение

t.Invoke(new Func<int>(() =>

{

//Список операторов

}));

2.3.6 Выводы

В данной главе проведен обзор и анализ существующих решений в области управления транзакциями в СУБД, рассмотрены пути увеличения производительности, использующиеся в системах управления распределенными транзакциями, изучены средства удаленного взаимодействия с объектами и выбраны средства организации управления транзакциями Microsoft .NET Framework. Предложенный алгоритм работы подсистемы управления транзакциями позволяет при выборе оптимальных параметров инициализации добиться существенного увеличения производительности серверной части АСУД «ЕВФРАТ». Реализован программный модуль - подсистема управления транзакциями на основе предложенного алгоритма, позволяющий создавать транзакции, в рамках транзакции выполнять операции с хранилищем и файлами, осуществлять фиксацию или откат транзакции пользователем и производить автоматический откат в случае возникновения ошибки, выполнять транзакции в заданном числе потоков - подсистема осуществляет распределение транзакций по потокам в зависимости от их загруженности для параллельной обработки, настраивать количество потоков для достижения максимальной производительности а так же интервал времени для периодических работ, планировать выполнение периодической работы во время простоя потоков, а так же не реже, чем через заданный интервал времени во время работы потоков. Полученная подсистема позволяет так же использовать технологию xNika для работы с данными, специфичными для автоматизированных системы управления документами, как с объектами - на высоком уровне. Проведено исследование показателей производительности системы с использованием разработанной подсистемы управления транзакциями и произведено сравнение с прежними показателями - в итоге были достигнуты лучшие показатели. Производительность алгоритмов оказалась заметной при тестировании на архитектуре с 2-ядерным процессором и значительно превышает прежние показатели на архитектуре с 4-ядерным процессором.

3. Экологическая часть и безопасность жизнедеятельности

3.1 Исследование воздействия опасных и вредных факторов при эксплуатации ЭВМ и их воздействие на организм человека

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

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

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

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

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

1. Персональный компьютер IBM PС:

· частота процессора - 3000 МГц;

· оперативная память - 2Гб;

· жесткий диск - 80Гб;

· DVD-ROM;

· напряжение питания - 220 В.

2. Монитор SyncMaster 931BF:

· потребляемая мощность - 38 Вт;

· величина зерна - 0,294 мм;

· максимальное разрешение - 1280 x 1024 при 75Гц;

· напряжение питания - 220 В.

При использовании указанных элементов вычислительной техники могут возникнуть опасные и вредные факторы.

1. Безопасным для человека считается напряжение менее 40В. Персональный компьютер питается от двухфазной сети переменного тока с частотой 50Гц и напряжением 220В. Это напряжение является опасным для человека, поскольку прикосновение к токоведущим частям может привести к поражению электрическим током, что обуславливает появление опасного фактора - поражение электрическим током.

Воздействие электрического тока на человека может носить следующий характер:

· термический - нагрев тканей,

· электролитический - влияние на состав крови,

· биологический - раздражение нервных окончаний тканей, судорожное сокращение мышц,

· механический - разрыв тканей, получение ушибов, вывихов как следствие потери координации движений после поражения электрическим током.

При поражении электрическим током человек может получить травмы следующего вида:

Общие травмы - электроудары. Различают электроудары четырех степеней сложности:

· первая степень: судорожное болезненное сокращение мышц без потери сознания;

· вторая степень: судорожное болезненное сокращение мышц, сопровождающееся потерей сознания, но с сохранением дыхания и сердцебиения;

· третья степень: судорожное сокращение мышц, потеря сознания, нарушение работы сердца или дыхания (либо и то, и другое вместе);

· четвертая степень: наступление клинической смерти, т.е. прекращение дыхания и кровообращения.

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

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

· может вызвать обострение некоторых кожных заболеваний: угревой сыпи, себорроидной экземы, розового лишая, рака кожи и др.;

· воздействие на метаболизм может вызвать изменение биохимической реакции крови на клеточном уровне, что ведет к стрессу;

· может возникнуть нарушение в протекании беременности;

· способствует увеличению возможности выкидыша у беременных в два раза;

· способствует нарушению репродуктивной функции и возникновению злокачественных образований;

· способствует нарушению терморегуляции организма;

· способствует изменениям в нервной системе (потере порога чувствительности);

· может привести к понижению/повышения артериального давления;

· может привести к функциональным нарушениям сердечно-сосудистой и центральной нервной систем человека.

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

3. Во время работы на персональных ЭВМ при прикосновении к любому из элементов оборудования могут возникнуть разрядные токи статического электричества. Вследствие этого происходит электризация пыли и мелких частиц, которые притягивается к экрану. Собравшаяся на экране электризованная пыль ухудшает видимость, а при повышении подвижности воздуха в помещении более 0.2 м/с, попадает на лицо и в легкие человека, вызывая заболевания кожи и дыхательных путей. Статическое электричество при превышении нормированного значения 15 кВ/м становится вредным фактором.

Особенно электростатический эффект наблюдается у компьютеров, которые находятся в помещении с полами, покрытыми синтетическими коврами.

При повышении напряженности поля Е>15 кВ/м, статическое электричество может привести к выходу компьютера из строя, замыканию клавиатуры и потере информации на экране.

4. К вредным факторам при работе за компьютером можно также отнести блики и мерцание экрана из-за низкой частоты вертикального обновления или из-за низкого качества развертки монитора. Экспериментальные данные показывают, что вышеуказанные факторы способствуют возникновению:

· близорукости и переутомлению глаз;

· мигрени и головной боли;

· раздражительности, нервному напряжению и стрессу.

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

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

3.2 Способы защиты пользователей от опасных и вредных факторов

Для защиты от напряжения прикосновения используется зануление. Занулением называется преднамеренное соединение нетоковедущих частей с нулевым защитным проводником (рис. 3.1). Оно применяется в трехфазных четырехпроводных сетях с заземленной нейтралью в установках до 1000 вольт и является основным средством обеспечения электробезопасности.

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

Рисунок 3.1 - Зануление

Расчет возможной величины тока короткого замыкания производится на основе следующих данных:

1. Коэффициент, учитывающий тип защитного устройства: k=3;

2. Фазовое напряжение: U=220В;

3. Паспортная величина сопротивления обмотки трансформатора:

= 0.312 Ом;

4. Удельное сопротивление медных проводников: =0.0175Ом*м;

5. Удельное сопротивление алюминиевых проводников: =0.0280Ом*м;

6. Расчет величины возможного тока короткого замыкания по заданным параметрам:

,(3.1)

где Iкз - ток короткого замыкания [А];

Uф - фазовое напряжение [B];

Rобщ - общее сопротивление цепи [Ом];

rт- сопротивление катушек трансформатора [Ом].

,(3.2)

где r1 и r2 - сопротивление первого и второго проводника соответственно [Ом];

rнзп - сопротивление нулевого защитного проводника [Ом];

7. Расчет сопротивления проводника производится по формуле:

,(3.3)

где - удельное сопротивление материала проводника [Ом*м];

l - длина проводника [м];

S - площадь поперечного сечения проводника [мм2].

Таким образом, получаем следующие значения:

= 0.0280*(500/2)=7 (Ом);

= 0,0175*(20/1)=0.35(Ом);

= 0,0175*(15/1)=0.2625(Ом);

= 7+0.35+0.2625=7.6125 (Ом);

= 220/(0.312/ 3 + 7.6125) = 28.51 (А).

По величине тока короткого замыкания определим с каким необходимо к цепь питания ПЭВМ включить автомат. При замыкании фазы на зануленный корпус электроустановка автоматически отключается, если ток однофазного короткого замыкания удовлетворяет условию:

,(3.4)

где - номинальный ток срабатывания защитного устройства, [А];

k - коэффициент, учитывающий тип защитного устройства.

Таким образом, номинальный ток срабатывания защитного устройства:

.(3.5)

= 28.51/3=9.5 (А).

Отсюда следует, что во избежание поражения электрическим током и выхода из строя ПЭВМ и периферийного оборудования, в случае возникновения короткого замыкания или других причин появления напряжения прикосновения в цепь питания ПЭВМ необходимо включить автомат с номинальным током = 10А.

Для снижения уровня воздействия электромагнитных полей желательно пользоваться следующими мерами:

· Осуществлять экранирование экрана монитора, суть которого заключается в покрытии поверхности экрана слоем оксида олова, либо в стекло электролучевой трубки добавляется оксид свинца;

· Удалять рабочее место от источника электромагнитного поля: оператор должен находиться на расстоянии вытянутой руки от экрана монитора;

· Необходимо рациональное размещение оборудования. Располагать ЭВМ следует на расстоянии не менее 1.22 м от боковых и задних стенок других мониторов;

· Запрещается работать при снятых внешних кожухах (корпусах) персональных компьютеров;

· Необходимо ограничивать время работы за компьютером. Время непрерывной работы должно составлять не более 4 часов в сутки. За неделю суммарное время работы не должно превышать 20 часов.

Защита от статического электричества достигается:

1. Установкой контурного заземления;

2. Установкой нейтрализаторов статического электричества;

3. Использованием экранов для снятия статики;

4. Наличием антистатичных полов;

5. Проведением влажной уборки;

6. Проветриванием помещений с подвижностью воздуха 0,1 - 0,2 м/с без присутствия пользователей.

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

Блики на экране монитора могут возникнуть из-за неправильного освещения в помещении.

3.3 Выводы

транзакция пользователь управление

При использовании человеком вычислительной техники могут возникнуть опасные и вредные факторы, такие как: поражение электрическим током, излучение электромагнитных полей низкой частоты, статическое электричество. Необходимо не только знать о влиянии на человека данных факторов, но и уметь обезопасить себя от их воздействия. Безопасность при работе с ЭВМ может быть обеспечена за счет:

· правильного выбора визуальных параметров дисплея,

· рационального размещения компьютеров в помещениях,

· применения средств защиты от вредных и опасных факторов,

· правильного подбора освещения и микроклимата в помещении.

Используемые методы и способы по защите от воздействия опасных и вредных факторов обеспечивают безопасность разработчика и пользователей.

Заключение

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

1. Проведен обзор и анализ существующих решений в области управления транзакциями в СУБД, рассмотрены пути увеличения производительности, использующиеся в системах управления распределенными транзакциями, изучены средства удаленного взаимодействия с объектами и выбраны средства организации управления транзакциями Microsoft .NET Framework;

2. Предложен алгоритм работы подсистемы управления транзакциями, позволяющий при выборе оптимальных параметров инициализации добиться существенного увеличения производительности серверной части системы «ЕВФРАТ»;

3. Реализован программный модуль - подсистема управления транзакциями на основе предложенного алгоритма, позволяющий:

a. Создавать транзакции;

b. В рамках транзакции выполнять операции с хранилищем и файлами;

c. Осуществлять фиксацию или откат транзакции пользователем и производить автоматический откат в случае возникновения ошибки;

d. Выполнять транзакции в заданном числе потоков - подсистема осуществляет распределение транзакций по потокам в зависимости от их загруженности для параллельной обработки;

e. Настраивать количество потоков для достижения максимальной производительности, а так же интервал времени для периодических работ;

f. Планировать выполнение периодической работы во время простоя потоков, а так же не реже, чем через заданный интервал времени во время работы потоков;

g. Использовать технологию xNika для работы с данными, специфичными для системы «ЕВФРАТ», как с объектами - на высоком уровне - упрощенным способом.

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

5. Экологическая часть содержит исследование опасных и вредных факторов при работе с ЭВМ и методы защиты пользователей от их воздействия.

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

Список литературы

1 The Notions of Consistency and Predicate Locks in a Database System - K. Eswaran, J. Gray, R. Lorie, I. Traiger - Communications of the ACM. - 1976. - №19. - С. 624-633. - ISSN:0001-0782

2 Основы систем баз данных - Дж. Ульман - Финансы и статистика, Москва. - 1983. - 334 с

3 On Optimistic Methods for Concurrency Control - H.T. Kung, J.T. Robinson - ACM Transactions on Database Systems. - 1981. - №6(2). - С.213-226

4 Optimistic Concurrency Control Algorithm with Dynamic Serialization Adjustment for Firm Deadline Real-Time Database Systems - P. Krzyzagrski, T. Morzy - Second International Workshop on Advances in Databases and Information Systems (ADBIS"95) . - 1995. - №1. - С.21-28

5 Concurrency control performance modeling: alternatives and implications - R. Agrawal, M.J. Carey, M. Livny - ACM Transactions on Database Systems. - 1987. - №12(4). - С.609-654

6 The performance of Concurrency Control Algorithms for Database management Systems - M.J. Carey, M.R. Stonebraker - 10th VLDB Conference, Singapore. - 1984

7 Real-Time Databases - K. Ramamritham - International Journal of Distributed and Parallel Databases. - 1992. - №1(1)

8 Scheduling Real-Time Transactions: A performance Evaluation - R. Abbott, H. Garcia-Molina - 14th VLDB Conference. - 1988

9 Scheduling Real-Time Transactions with Disk Resident Data - R. Abbott, H. Garcia-Molina - 15th VLDB Conference. - 1989

10 Dynamic Real-Time Optimistic Concurrency Control - J.R. Haritsa, M.J. Carey, M. Livny - IEEE Real-Time Systems Simposium, Orlando, Florida. - 1990

11 Введение в системы баз данных - К.Дж. Дейт - Изд. Дом «Вильямс». - 2008. - 1328 с. - ISBN 978-5-8459-0788-2, 0-321-19784-4

12 C# 2005 и платформа .NET 3.0 для профессионалов - К. Нейгл, Б. Ивьен, Д. Глинн, М. Скиннер и др. - Диалектика. - 2008. - 1376 с. - ISBN 978-5-8459-1317-3

13 От баз данных к базам знаний (объекты, формы, содержание) - Арлазаров В.Л., Емельянов Н.Е. - 2010

14 Электронный документооборот по технологии клиент-сервер - Даниленко А.Ю., Подрабинович А.А., Сургучев В.А., Хлюстов К.В. - 2004

15 Особенности систем, создаваемых на основе НИКА - Технологии - Емельянов Н.Е., Ерохин В.И. - 2009

16 Богданов А.С., Емельянов Н.Е., Ерохин В.И., Скорняков В.А., Романов Б.Л. НИКА-технология построения информационных систем - Организационное управление и искусственный интеллект - Сб. трудов ИСА РАН. Под ред. члена-корр. РАН Арлазарова В.Л. и д.т.н. проф. Емельянова Н.Е. - М.: Едиториал УРСС, 2003.

Приложения

Текст программы

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

namespace Cognitive.Threading

{

/// <summary>

/// делегат для обработки событий пула потоков

/// </summary>

/// <param name="source"></param>

public delegate void ThreadPoolEvent(ThreadPool source);

/// <summary>

/// пул потоков для обработки заданий

/// </summary>

public class ThreadPool

{

private List<WorkingThread> m_threads = new List<WorkingThread>();

/// <summary>

/// конструктор объекта

/// </summary>

/// <param name="count">Количество рабочих потоков

/// <remarks>установка количества рабочих потоков больше числа

/// процессоров на компьютере

/// может привести к снижению суммарной производительности</remarks>

/// </param>

/// <param name="idleInterval">максимальный интервал между обработкой событий простоя

/// <see cref="ThreadPool.OnIdle"/>

/// </param>

/// <remarks>

/// Выполняет запуск указанного количества рабочих потоков.

/// </remarks>

public ThreadPool(int count, TimeSpan idleInterval)

{

if (count <= 0)

throw new ArgumentException("Количество потоков должно быть неотрицательным числом или неравно нулю");

if (idleInterval <= TimeSpan.Zero)

throw new ArgumentException("Максимальный интервал между обработкой события простоя не должен быть отрицательным числом.");

if (idleMinInterval > idleInterval)

idleMinInterval = idleInterval;

for (int i = 0; i < count; i++)

{

WorkingThread thread = new WorkingThread(

TimeSpan.FromTicks(idleMinInterval.Ticks * 2/ 3), idleInterval);

thread.OnIdle += new EventHandler(thread_OnIdle);

m_threads.Add(thread);

}

}

private volatile bool _InIdle = false;

private DateTime lastIdle = DateTime.Now;

/// <summary>

/// минимальный интервал вызова обработчика события Idle

/// при отсуствии задач для обработки

/// </summary>

private TimeSpan idleMinInterval = TimeSpan.FromMilliseconds(100);

private void thread_OnIdle(object sender, EventArgs e)

{

if (OnIdle == null)

return;

lock (this)

{

if (_InIdle || (lastIdle + idleMinInterval) > DateTime.Now)

return;

_InIdle = true;

}

OnIdle(this);

lastIdle = DateTime.Now;

_InIdle = false;

}

//private bool m_stopping = false;

private bool m_stopping = false;

/// <summary>

/// Пул находится в состоянии останова

/// </summary>

public bool Stopping

{

get

{

return m_stopping;

}

}

/// <summary>

/// останавливает все запущенные рабочие потоки

/// </summary>

public void Stop()

{

m_stopping = true;

//Блокируем потоки, меняем статус на останов

foreach (WorkingThread thread in m_threads)

{

thread.OnIdle -= thread_OnIdle;

thread.StartStop();

}

//Ждем освобождения их очередей

foreach (WorkingThread thread in m_threads)

thread.queue.Empty.WaitOne();

//Ждем пока потоки затерминируются

foreach (WorkingThread thread in m_threads)

thread.Stop();

m_threads.Clear();

}

/// <summary>

/// добавляет задачу для выполнения

/// </summary>

/// <param name="wi">Задача для выполнения</param>

/// <remarks>

/// добавляет задачу для выполнения в очередь одного из рабочих потоков.

/// Выбирается наименее загруженный поток -

/// который простаивает или тот, у которого наименее короткая очередь

/// </remarks>

public void Push(WorkItem wi)

{

if (m_stopping)

throw new InvalidOperationException("Пул находится в состоянии останова и не может принимать задачи");

// throw new InvalidOperationException("Пул находится в состоянии останова и не может принимать задачи");

if (m_threads.Count == 0)

throw new InvalidOperationException("В пуле нет ни одного потока");

//рассматриваю список тредов, если тредов несколько

WorkingThread thread = m_threads[0];

if (m_threads.Count > 1)

{

//Ищу наименее загруженные

for (int i = 1; i < m_threads.Count; i++)

{

if (((m_threads[i].Сount == thread.Сount && m_threads[i].State > thread.State)

|| m_threads[i].Сount < thread.Сount) && m_threads[i].State != WorkingThreadStates.Stopping)

{

thread = m_threads[i];

}

}

}

thread.queue.Push(wi);

}

/// <summary>

/// событие простоя

/// </summary>

/// <remarks>

/// события простоя возникает когда любой из рабочих потоков входит в состояние простоя или

/// с момента обработки последнего события простоя прошло времени больше, чем было указано

/// при конструировании объекта.

///

/// Событие простоя может использоваться для запуска фоновых задач

/// </remarks>

public event ThreadPoolEvent OnIdle;

}

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

using System.Runtime.InteropServices;

namespace Cognitive.Threading

{

/// <summary>

/// состояния рабочих потоков

/// </summary>

public enum WorkingThreadStates

{

/// <summary>

/// поток находится в процессе запуска

/// </summary>

Starting = 1,

/// <summary>

/// поток находится в состоянии обработки задания из очереди

/// </summary>

Working = 2,

/// <summary>

/// поток находится в состоянии ожидания очередного задания

/// </summary>

Idle = 3,

/// <summary>

/// поток находится в состоянии завершения

/// </summary>

Stopping = 0

}

/// <summary>

/// рабочий поток

/// </summary>

/// <remarks>

/// Управляет очередью задач в рамках потока.

/// Все обращения к методам экземпляра класса являются потокозащищенными

/// </remarks>

public class WorkingThread

{

private WorkItemsQueue m_witems = new WorkItemsQueue();

private Thread m_thread = null;

private ThreadContext m_ctx = new ThreadContext();

private ManualResetEvent m_stoppingThread = new ManualResetEvent(false);

private volatile WorkingThreadStates m_state = WorkingThreadStates.Idle;

private DateTime lastIdle = DateTime.Now;

private TimeSpan idleMaxInterval = TimeSpan.Zero; //TimeSpan.FromSeconds(5);

private TimeSpan idleMinInterval = TimeSpan.Zero; //TimeSpan.FromSeconds(5);

private Func<TimeSpan, TimeSpan, TimeSpan> max = (x, y) => { if (x > y) return x; return y; };

private void Work()

{

//указываем текущий поток

__current = this;

WaitHandle[] waitfor = new WaitHandle[] { m_witems.Received, m_stoppingThread };

while (!m_stoppingThread.WaitOne(0, false))

{

//Очередь пуста или таймаут ожидания обработки Idle

//и не в состоянии завершения

if (((!m_witems.Received.WaitOne(0, false))

|| (lastIdle + idleMaxInterval) < DateTime.Now)

&& (m_state != WorkingThreadStates.Stopping))

{

m_state = WorkingThreadStates.Idle;

if (OnIdle != null)

OnIdle(this, EventArgs.Empty);

lastIdle = DateTime.Now;

}

int waitRes = WaitHandle.WaitAny(waitfor, idleMinInterval, false);

if (waitRes != 0) //останов или таймаут

continue;

//waitRes = 0, что-то помещено в очередь

if (m_state != WorkingThreadStates.Stopping)

m_state = WorkingThreadStates.Working;

while (!m_stoppingThread.WaitOne(0, false) &&

(m_witems.Length > 0) &&

(lastIdle + idleMaxInterval) > DateTime.Now)

{

WorkItem wi = null;

if (m_witems.TryGet(out wi))

{

Context.Clear();

wi.Do();

}

}

}

}

/// <summary>

/// Общее количество задач в потоке

/// </summary>

public int Сount

{

get

{

return m_witems.Length;

}

}

/// <summary>

/// очередь задач потока (не содержит ожидающих блокировку задач, которые могут быть в потоке)

/// </summary>

public WorkItemsQueue queue { get { return m_witems; } }

/// <summary>

/// конструктор потока

/// </summary>

/// <param name="idleMax">Максимальный интервал между обработками события Idle, д.б. больше 5 сек</param>

/// <remarks>

/// выполняет запуск рабочего потока для выполнения задач

/// </remarks>

public WorkingThread(TimeSpan idleMin, TimeSpan idleMax)

{

if (idleMin > idleMax)

throw new ArgumentException();

m_state = WorkingThreadStates.Starting;

m_thread = new Thread(Work);

idleMaxInterval = idleMax;

idleMinInterval = idleMin;

m_thread.Start();

m_thread.IsBackground = false;

}

public event EventHandler OnIdle;

/// <summary>

/// останавливает поток.

/// </summary>

/// <remarks>

/// Блокирует добавление новых заданий в поток и завершает выполнения потока.

/// Выполняется с ожиданием завершения потока.

/// Эта функция не может вызвана из самого рабочего потока

/// </remarks>

public void StartStop()

{

m_state = WorkingThreadStates.Stopping;

m_witems.Block();

}

/// <summary>

/// инициирует процедуру остановки потока без ожидания завершения и без блокировки

/// </summary>

public void Stop()

{

m_stoppingThread.Set();

m_thread.Join();

}

/// <summary>

/// состояния потока в настоящее время

/// </summary>

public WorkingThreadStates State

{

get{

return m_state;

}

}

/// <summary>

/// контекст выполнения текущей задачи

/// </summary>

/// <remarks>контекст выполнения задачи инициализируется классами,

/// который помещают задачу в поток, в обработчике события WorkItem.WorkStarting.

/// Контекст автоматически очищается после выполнения каждой задачи

/// </remarks>

public ThreadContext Context

{

get{

return m_ctx;

}

}

/// <summary>

/// Идентификатор соответствующего потока

/// </summary>

public int ManagedThreadId

{

get

{

return m_thread.ManagedThreadId;

}

}

[ThreadStatic]

private static WorkingThread __current = null;

/// <summary>

/// возвращает текущий объект рабочего потока

/// </summary>

/// <remarks>Если вызов производится в рамках рабочего потока, то

/// возвращает соответствующий объект рабочего потока,

/// иначе позвращает null

/// </remarks>

public static WorkingThread Current

{

get

{

return __current;

}

}

}

/// <summary>

/// контекст выполнения задачи в рабочем потоке

/// </summary>

public class ThreadContext : System.Collections.Generic.Dictionary<string, Object>

{

}

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

namespace Cognitive.Threading

{

/// <summary>

/// очередь задач на исполнение

/// </summary>

/// <remarks>

/// Все обращения к методам экземпляра класса являются потокозащищенными

/// </remarks>

public class WorkItemsQueue

{

private Queue<WorkItem> m_queue = new Queue<WorkItem>();

private bool m_blocked = false;

private ManualResetEvent m_received = new ManualResetEvent(false);

private ManualResetEvent m_empty = new ManualResetEvent(true);

/// <summary>

/// В очереди появились задачи

/// </summary>

public ManualResetEvent Received

{

get

{

return m_received;

}

}

/// <summary>

/// Очередь освободилась

/// </summary>

public ManualResetEvent Empty

{

get

{

return m_empty;

}

}

/// <summary>

/// добавляет задачу в очередь

/// </summary>

/// <param name="wi">Задача для выполнения</param>

public void Push(WorkItem wi)

{

lock (m_queue)

if (!m_blocked)

{

m_queue.Enqueue(wi);

m_received.Set();

m_empty.Reset();

}

else

throw new ArgumentException("Рабочий поток в состоянии завершения и не может принимать workitems");

}

/// <summary>

/// попытка получить очередную задачу из очереди

/// </summary>

/// <param name="wi">Возвращаемый параметр - задача для исполнения</param>

/// <returns>Если задача успешно получена, то возвращается true.

/// Если очередь пуста - то возвращается false</returns>

public bool TryGet(out WorkItem wi)

{

wi = null;

lock (m_queue)

{

if (m_queue.Count == 0)

return false;

wi = m_queue.Dequeue();

if (m_queue.Count == 0)

{

m_received.Reset();

m_empty.Set();

}

}

return wi != null;

}

/// <summary>

/// ожидание появления в очереди задачи для выполнения

/// </summary>

/// <param name="ts">Время в течение которого выполнять ожидание</param>

/// <returns>true если ожидание выполнено успешно и задача в очереди появилась,

/// false если указанное время прошло, а задачи так и не появилось</returns>

/// <remarks> Пока выполняется ожидание вызывающий поток не работает.</remarks>

public bool Wait(TimeSpan ts)

{

return m_received.WaitOne(ts, false);

}

/// <summary>

/// блокировка очереди

/// </summary>

/// <remarks>запрещает добавление новых элементов в очередь</remarks>

public void Block()

{

m_blocked = true;

}

/// <summary>

/// является ли очередь заблокированной

/// </summary>

public bool Blocked

{

get

{

return m_blocked;

}

}

/// <summary>

/// длина очереди

/// </summary>

public int Length

{

get

{

lock (m_queue)

{

return m_queue.Count;

}

}

}

}

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Threading;

using System.Linq.Expressions;

using System.Runtime.InteropServices;

namespace Cognitive.Threading

{

/// <summary>

/// делегат события задачи, выполняющейся в пуле потоков

/// </summary>

/// <param name="source"></param>

public delegate void WorkItemEventDelegate(WorkItem source);

/// <summary>

/// делегат события об ошибке, возникшей при выполнении задачи в пуле потоко

/// </summary>

/// <param name="source"></param>

/// <param name="e"></param>

public delegate void WorkItemExceptionDelegate(WorkItem source, Exception e);

/// <summary>

/// задача для выполнения в пуле потоков

/// </summary>

public class WorkItem

{

ManualResetEvent m_completeHandle = new ManualResetEvent(false);

Delegate m_ItemsMethod;

Object[] m_args;

Object m_result = null;

String m_stack;

/// <summary>

/// конструктор задачи для выполнения

/// </summary>

/// <param name="method"></param>

/// <param name="parameters"></param>

public WorkItem(Delegate method, params Object[] parameters)

{

m_ItemsMethod = method;

m_args = parameters;

m_stack = (new System.Diagnostics.StackTrace(1)).ToString();

}

/// <summary>

/// событие начала работы над задачей

/// </summary>

public event WorkItemEventDelegate WorkStarting;

/// <summary>

/// событие активизации задачи для инициализации контекста

/// </summary>

public event WorkItemEventDelegate WorkActivating;

/// <summary>

/// событие окончания работы над задачей

/// </summary>

public event WorkItemEventDelegate WorkComplete;

/// <summary>

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

/// </summary>

public event WorkItemExceptionDelegate WorkException;

internal void Do()

{

try

{

Activate();

Start();

Invoke();

}

catch (System.Exception ex)

{

ProcessException(ex);

}

finally

{

Complete();

}

}

private void ProcessException(Exception e)

{

if (WorkException != null)

WorkException(this, e);

else

throw e;

}

private void Complete()

{

if (WorkComplete != null)

{

WorkComplete(this);

}

m_completeHandle.Set();

}

private void Invoke()

{

if (m_ItemsMethod != null)

m_result = m_ItemsMethod.DynamicInvoke(m_args);

}

private void Start()

{

if (WorkStarting != null)

WorkStarting(this);

}

private void Activate()

{

if (WorkActivating != null)

WorkActivating(this);

}

/// <summary>

/// результат выполнения задачи

/// </summary>

public Object Result

{

get

{

return m_result;

}

}

/// <summary>

/// Объект для асинхронного ожидания завершения выполнения задания. Может означать так же

/// принудительное завершение при останове пула потоков

/// </summary>

public WaitHandle AsyncWaitHandle

{

get

{

return m_completeHandle;

}

}

public delegate void anywork();

public delegate object anyworkandret();

}

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Cognitive.Docflow.Transactions;

using System.Diagnostics;

namespace Cognitive.Docflow.Environment

{

public class BlockManager

{

/// <summary>

/// словарь активных блокировок

/// </summary>

Dictionary<String, Transaction> _activeLocks = new Dictionary<string, Transaction>();

/// <summary>

/// попытка войти в блокировку в текущей транзакции

/// </summary>

/// <param name="blockId">идентификатор блокировки</param>

/// <returns>результат - удалось или нет</returns>

public bool TryEnterBlock(String blockId)

{

lock (_activeLocks)

{

Transaction trans;

if (!_activeLocks.TryGetValue(blockId, out trans))

{

Transaction.Current.Complete += new TransactionEventHandler(Current_Complete);

_activeLocks.Add(blockId, Transaction.Current);

Trace.WriteLine("EnterLock: " + blockId + " trans: " + Transaction.Current.ID);

return true;

}

if (trans.Equals(Transaction.Current))

{

Trace.WriteLine("EnterLock: " + blockId + " trans: " + Transaction.Current.ID);

return true;

}

return false;

}

}

public bool IsInLock(Transaction test, String lockId)

{

lock(_activeLocks)

{

Transaction trans;

if (_activeLocks.TryGetValue(lockId, out trans))

return test.Equals(trans);

return false;

}

}

void Current_Complete(Transaction sender, EventArgs e)

{

///удаление всех активных блокировок для указанной транзакции

lock(_activeLocks)

{

List<string> keys = new List<string>();

foreach(KeyValuePair<String, Transaction> pair in

_activeLocks.Where(

delegate(KeyValuePair<String, Transaction> p ){

return p.Value.Equals(sender);

}))

{

Trace.WriteLine("LeaveLock: " + pair.Key + " trans: " + sender.ID);

keys.Add(pair.Key);

}

foreach (string k in keys)

{

_activeLocks.Remove(k);

}

}

}

}

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

namespace Cognitive.Docflow.Transactions

{

/// <summary>

/// класс, управляющий набором соединений со средой хранения

/// </summary>

/// <remarks>

/// Управляет соединениями.

/// Каждое соединение используется в том потоке, в котором было создано.

/// Для каждого потока существует свой набор соединений.

/// Соединение бывает свободным и занятым.

/// </remarks>

public class ConnectionPool

{

private static CTNKDESMLib.ICTDEConnector s_conn = new XNika.SQL.XNSQLConnector();

/// <summary>

/// Состояния соединения

/// </summary>

private enum ConnectionStateEnum

{

/// <summary>

/// Соединение занято

/// </summary>

BUSY,

/// <summary>

/// Соединение свободно

/// </summary>

FREE

}

private String m_sqlConnString;

private Dictionary<int, Dictionary<CTNKDESMLib.ICTDEDatabase, ConnectionStateEnum>> m_connections;

private String m_login, m_password;

/// <summary>

/// строка подключени к MS SQL

/// </summary>

public String ConnectionString

{

get { return m_sqlConnString; }

}

/// <summary>

/// конструктор

/// </summary>

/// <param name="sqlConnectionString"></param>

/// <param name="login"></param>

/// <param name="password"></param>

public ConnectionPool(String sqlConnectionString, String login, String password)

{

m_login = login;

m_password = password;

m_sqlConnString = sqlConnectionString;

m_connections = new Dictionary<int, Dictionary<CTNKDESMLib.ICTDEDatabase, ConnectionStateEnum>>();

}

/// <summary>

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

/// В случае отсутствия свободного соединения создается новое

/// Возвращаемое соединение отмечается как занятое и остается таким до вызова

/// функции FreeConnection

/// </summary>

/// <returns></returns>

public CTNKDESMLib.ICTDEDatabase GetConnection()

{

int currThread = System.Threading.Thread.CurrentThread.ManagedThreadId;

CTNKDESMLib.ICTDEDatabase db;

Dictionary<CTNKDESMLib.ICTDEDatabase, ConnectionStateEnum> threadConnections = null;

lock (m_connections)

{

if (m_connections.ContainsKey(currThread))

{

threadConnections = m_connections[currThread];

//Ищем свободное

if (threadConnections.ContainsValue(ConnectionStateEnum.FREE))

foreach (KeyValuePair<CTNKDESMLib.ICTDEDatabase, ConnectionStateEnum> pair in threadConnections)

if (pair.Value == ConnectionStateEnum.FREE)

return pair.Key;

}

}

//Нужно новое соединение создаем

db = s_conn.Open(m_sqlConnString, m_login, m_password);

///формат поиска

((CTNKDESMLib.ICTDEDatabase2)db).queryFormat = CTNKDESMLib.tagCTDEQueryFormat.CTDE_QF_XPATH_STRING;

if (threadConnections == null)

{

//если нет словаря соединений для текущего потока - добавляем

threadConnections = new Dictionary<CTNKDESMLib.ICTDEDatabase, ConnectionStateEnum>();

lock (m_connections)

{

m_connections.Add(currThread, threadConnections);

}

}

//добавляем новое соединение в словарь

threadConnections.Add(db, ConnectionStateEnum.BUSY);

return db;

}

/// <summary>

/// помечает указанное соединение как свободное

/// </summary>

/// <param name="connection"></param>

public void FreeConnection(CTNKDESMLib.ICTDEDatabase connection)

{

int currThread = System.Threading.Thread.CurrentThread.ManagedThreadId;

lock (m_connections)

{

if (m_connections.ContainsKey(currThread) &&

m_connections[currThread].ContainsKey(connection))

m_connections[currThread][connection] = ConnectionStateEnum.FREE;

}

}

}

}

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using Cognitive.Docflow;

using System.Collections;

using Cognitive.Threading;

using System.Data.SqlClient;

using System.Data.Common;

using System.Diagnostics;

namespace Cognitive.Docflow.Transactions

{

/// <summary>

/// делегат конструирования корневого объекта бизнес-логики

/// </summary>

/// <param name="datasource"></param>

/// <returns></returns>

public delegate Environment.IDFContainerObject

CreateRootObjectDelegate(CTNKDESMLib.ICTDEDatabase datasource);

/// <summary>

/// делегат события транзакции

/// </summary>

/// <param name="sender"></param>

/// <param name="e">параметры события</param>

public delegate void TransactionEventHandler(Transaction sender, EventArgs e);

/// <summary>

/// объект транзакции

/// </summary>

public class Transaction: Environment.IDFObjectsFactory

{

private static volatile int _index = 0;

private DateTime _MyStartTime;

private DateTime _MyIdleStart;

/// <summary>

/// Время простоя транзакции

/// </summary>

public TimeSpan MyIdleInterval

{

get

{

if (_running == null)

return DateTime.Now - _MyIdleStart;

return TimeSpan.Zero;

}

}

private int _MyIndex;

private ConnectionPool _cpool;

private System.Transactions.CommittableTransaction _cTrans;

SqlConnection _sqlConn;

private CTNKDESMLib.ICTDEDatabase _connection;

private Environment.EnvironmentServer _server;

private TransactionContext _ctx;

private Dictionary<String, TransactionFile> _transactionFiles;

/// <summary>

/// Очередь задач транзакции - задачи в ожидании

/// </summary>

private Queue<Cognitive.Threading.WorkItem> _transactionQueue;

/// <summary>

/// обрабатываемая в настоящий момент задача

/// </summary>

private WorkItem _running;

/// <summary>

/// Транзакция находится в состоянии завершения и не может принимать новых задач

/// </summary>

private bool _commitFlag = false;

private bool _rollbackFlag = false;

private object _locker = new object();

private System.Threading.ManualResetEvent _completeHandle = new System.Threading.ManualResetEvent(false);

/// <summary>

/// Устанавливается, когда транзакция выполнилась и освободила свои ресурсы

/// </summary>

public System.Threading.WaitHandle CompleteHandle

{

get

{

return _completeHandle;

}

}

/// <summary>

/// рабочий поток в котором работает транзакция

/// </summary>

private WorkingThread _myThread;

/// <summary>

/// конструктор объекта Транзакция

/// </summary>

/// <param name="ctor">делегат конструирования корневого объекта бизнес-логики</param>

/// <param name="cpool">пул соединений</param>

/// <param name="thrd">рабочий поток, соответствующий транзакции</param>

private Transaction(Environment.EnvironmentServer server,

ConnectionPool cpool, Cognitive.Threading.WorkingThread thrd)

{

_MyIndex = ++_index;

_MyStartTime = DateTime.Now;

//тайм-аут у транзакции 1 час

_cTrans = new System.Transactions.CommittableTransaction(TimeSpan.FromHours(1));

System.Transactions.Transaction.Current = _cTrans;

_sqlConn = new SqlConnection(cpool.ConnectionString);

_sqlConn.Open();

Microsoft.Samples.DbConnectionScope.DbConnectionScope _conScope = new Microsoft.Samples.DbConnectionScope.DbConnectionScope();

_conScope.AddConnection(cpool.ConnectionString, _sqlConn);

using (_conScope)

{

_server = server;

_ctx = new TransactionContext();

_connection = cpool.GetConnection();

_cpool = cpool;

_myThread = thrd;

_myThread.OnIdle += new EventHandler(_myThread_OnIdle);

_transactionFiles = new Dictionary<string, TransactionFile>();

_transactionQueue = new Queue<Cognitive.Threading.WorkItem>();

_conScope.AddConnection(cpool.ConnectionString, new SqlConnection());

}

_MyIdleStart = DateTime.Now;

}

void _myThread_OnIdle(object sender, EventArgs e)

{

if (_commitFlag || _rollbackFlag)

return;

//Таймаут транзакции = 1 час

if ((DateTime.Now - _MyStartTime) < TimeSpan.FromHours(1))

return;

_myThread.OnIdle -= _myThread_OnIdle;

Rollback();

}

public int ID

{

get

{

return _MyIndex;

}

}

/// <summary>

/// освобождение ресурсов транзакции

/// </summary>

/// <remarks>

/// вызывается из методов Commit или Rollback

/// </remarks>

private void FreeResources()

{

_cpool.FreeConnection(_connection);

_sqlConn.Dispose();

lock (_locker)

{

foreach (KeyValuePair<String, TransactionFile> pair in _transactionFiles)

pair.Value.Dispose();

_transactionFiles.Clear();

_ctx.Clear();

}

if (Complete != null)

Complete(this, null);

_completeHandle.Set();

}

/// <summary>

/// Создание экземпляра новой транзакции

/// </summary>

/// <param name="server"></param>

/// <param name="cpool">пул соединений</param>

/// <param name="thpool">пул рабочих потоков</param>

/// <returns>сконструированный и проинициализированный объект транзакции</returns>

public static Transaction CreateInstance(Environment.EnvironmentServer server,

ConnectionPool cpool, Cognitive.Threading.ThreadPool thpool)

{

if (thpool.Stopping)

throw new InvalidOperationException("Нельзя создавать новые транзакции когда пул потоков в состоянии завершения");

Cognitive.Threading.WorkingThread wthr = Cognitive.Threading.WorkingThread.Current;

if (wthr == null)

{

Cognitive.Threading.WorkItem.anyworkandret CreateTrans = () =>

{

return Transaction.CreateInstance(server, cpool, thpool);

};

Cognitive.Threading.WorkItem wi =

new Cognitive.Threading.WorkItem(CreateTrans);

thpool.Push(wi);

wi.AsyncWaitHandle.WaitOne();

return wi.Result as Transaction;

}

else

{

return new Transaction(server, cpool, wthr);

}

throw new Exception();

}

/// <summary>

/// вызван метод Commit

/// </summary>

public event TransactionEventHandler OnCommit;

/// <summary>

/// вызыван метод Rollback

/// </summary>

public event TransactionEventHandler OnRollback;

/// <summary>

/// транзакция завершена (независимо от результата)

/// </summary>

public event TransactionEventHandler Complete;

/// <summary>

/// откат транзакции

/// </summary>

public void Rollback()

{

if (CompleteHandle.WaitOne(0))

return; //Этот хэндл выставляется когда у транзакции уже очистились ресурсы, поэтому в продолжении нет смысла

lock (_locker)

{

if (_commitFlag)

return;

//throw new Exception("Не могу сделать Rollback, когда уже был вызван Commit");

if (_rollbackFlag && (WorkingThread.Current == null || !WorkingThread.Current.Equals(_myThread)))

return; //Попытка повторно поставить в очередь откат

_rollbackFlag = true;

_myThread.OnIdle -= _myThread_OnIdle;

}

if (WorkingThread.Current != null && WorkingThread.Current.Equals(_myThread))

{

if (OnRollback != null)

OnRollback(this, null);

_cTrans.Rollback();

//добавляем задачу очистки ресурсов транзакции

_myThread.queue.Push(new WorkItem(new WorkItem.anywork(this.FreeResources)));

}

else

{

WorkItem.anywork w = () => { this.Rollback(); };

WorkItem wi = new WorkItem(w, null);

EnqueueWorkItem(wi);

wi.AsyncWaitHandle.WaitOne();

//_completeHandle.WaitOne();

}

}

/// <summary>

/// накат транзакции

/// </summary>

/// <remarks> если метод вызван из контекста транзакции или рабочего потока,

/// то в очередь транзакции помещается задание завершения транзакции и работа метода завершается

/// Если метод вызван вне контекста рабочих потоков,

/// то выполняется ожидание фактического завершения транзакции

/// </remarks>

public void Commit()

{

if (CompleteHandle.WaitOne(0))

return; //Этот хэндл выставляется когда у транзакции уже очистились ресурсы, поэтому в продолжении нет смысла

//сделать чтобы коммит или роллбэк был только один

lock (_locker)

{

if (_lastException != null) //уже было какое-то исключение

throw new InvalidOperationException("При выполнении транзакции возникло исключение", _lastException);

if (_rollbackFlag)

{

return;

//throw new Exception("Не могу вызвать Commit, так как уже был вызван Rollback");

}

if (_commitFlag && (WorkingThread.Current == null || !WorkingThread.Current.Equals(_myThread)))

return; //Попытка повторно поставить в очередь накат

_commitFlag = true;

_myThread.OnIdle -= _myThread_OnIdle;

}

if (WorkingThread.Current != null && WorkingThread.Current.Equals(_myThread))


Подобные документы

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.