Файл: 1_C#_Введение_в_программирование_Уч_пособ_(Марченко-2005).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 11.12.2025

Просмотров: 1394

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

Создаётся новый домен приложения с именем, заданным строкой-параметром, в рамках существующей политики безопасности:

public static AppDomain CreateDomain(string, Evidence);

Создаётся новый домен приложения using the specified name, evidence, and application domain setup information:

public static AppDomain CreateDomain(string, Evidence, AppDomainSetup);

Создаётся новый домен приложения the given name, using evidence, application base path, relative search path, and a parameter that specifies whether a shadow copy of an assembly is to be loaded into the application domain:

public static AppDomain CreateDomain(string, Evidence, string, string, bool);

Обзор пространства имён System.Threading

В этом пространстве объявляются типы, которые используются для создания многопоточных приложений: работа с потоком, средства синхронизации доступа к общим данным, примитивный вариант класса Timer… Много всего!

Тип

Назначение

 

 

 

 

 

Interlocked

Синхронизация доступа к общим данным.

 

 

Monitor

Синхронизация потоковых объектов при помощи блокировок и

 

управления ожиданием.

 

 

 

 

Mutex

Синхронизация ПРОЦЕССОВ.

 

 

 

 

Thread

Собственно класс потока, работающего в среде выполнения .NET. В

 

текущем домене приложения с помощью

этого класса

создаются

 

новые потоки.

 

 

 

 

ThreadPool

Класс,

предоставляющий

средства

управления

набором

 

взаимосвязанных потоков.

 

 

 

 

ThreadStart

Класс-делегат для метода, который должен быть выполнен перед

 

запуском потока.

 

 

 

 

Timer

Вариант

класса-делегата,

который

обеспечивает

передачу

 

управления некоторой функции-члену (неважно какого класса!) в

 

указанное время. Сама процедура ожидания выполняется потоком в

 

пуле потоков.

 

 

 

 

TimerCallback

Класс-делегат для объектов класса Timer.

 

 

WaitHandle

Объекты-представители

этого

класса

являются

объектами

 

синхронизации (обеспечивают многократное ожидание).

 

WaitCallback

Делегат, представляющий методы для рабочих элементов (объектов)

 

класса ThreadPool

 

 

 

 

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

МНОГОПОТОЧНАЯ ОС. Прежде всего, операционная система должна допускать параллельную (псевдопараллельную) работу нескольких программ.

Многопоточное приложение: отдельные компоненты работают одновременно (псевдоодновременно), не мешая друг другу.

Случаи использования многопоточности:

выполнение длительных процедур, ходом выполнения которых надо управлять,

функциональное разделение программного кода: пользовательский интерфейс – функции обработки информации,

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

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

Виды многопоточности

Переключательная многопоточность. Основа – резидентные программы. Программа размещалась в памяти компа вплоть до перезагрузки системы и управление ей

137


передавалось каким-либо заранее согласованным способом (предопределённой комбинацией клавиш на клавиатуре).

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

Вытесняющая многопоточность. ОС централизованно выделяет всем запущенным приложениям определённый квант времени для выполнения в соответствии с приоритетом приложения. Реальная возможность работы нескольких приложений в ПСЕВДОПАРАЛЛЕЛЬНОМ режиме. “Зависание” одного приложения не является крахом для всей системы и оставшихся приложений.

А кто в домене живёт…

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

приложения.

using System;

using System.Windows.Forms;

//Это пространство имён требуется для работы с классом Assembly. using System.Reflection;

//Это пространство имён требуется для работы с классом Process. using System.Diagnostics;

namespace AppDomain1

{

class MyAppDomain

{

public static void ShowThreads()

{

Process proc = Process.GetCurrentProcess(); foreach(ProcessThread aPhysicalThread in proc.Threads)

{

Console.WriteLine(aPhysicalThread.Id.ToString() + “:” + aPhysicalThread.ThreadState);

}

}

public static void ShowAssemblies()

{

// Получили ссылку на домен.

AppDomain ad = AppDomain.CurrentDomain;

//В рамках домена может быть множество сборок.

//Можно получить список список сборок домена. Assembly[] loadedAssemblies = ad.GetAssemblies();

//У домена имеется FriendlyName, которое ему присваивается

//при создании. При этом у него даже нет доступного конструктора. Console.WriteLine(“Assemblies in {0} domain:”, ad.FriendlyName); foreach(Assembly assembly in loadedAssemblies)

{

Console.WriteLine(assembly.FullName);

}

}

static void Main(string[] args)

{

Console.WriteLine(“=========================”);

//MessageBox.Show(“XXX”); - Это всего лишь вызов метода класса MessageBox.

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

//загружается сборка System.Windows.Forms.dll.

MessageBox.Show(“XXX”);

ShowThreads();

ShowAssemblies();

Console.WriteLine(“=========================”);

// Даже в таком простом приложении в рамках домена приложения живут три сборки!

}

}

}

138


Класс Thread. Общая характеристика

Thread класс представляет управляемые потоки. Создаёт потоки и управляет ими: устанавливает приоритет и статус потоков. Это объектная оболочка вокруг определённого этапа выполнения программы внутри домена приложения.

Статические

члены

Назначение

 

 

 

 

 

класса Thread

 

 

 

 

 

 

 

CurrentThread

 

Свойство. Только для чтения. Возвращает ссылку на поток,

 

 

выполняемый в настоящее время.

 

 

 

GetData()

 

Обслуживание слота текущего потока.

 

 

SetData()

 

 

 

 

 

 

 

GetDomain()

 

Получение ссылки на домен приложения (на ID домена), в рамках

GetDomainID()

 

которого работает указанный поток.

 

 

Sleep()

 

Блокировка выполнения потока на определенное время.

 

 

 

 

 

 

 

Нестатические члены

Назначение

 

 

 

 

 

IsAlive

 

Свойство. Если поток запущен, то true

 

 

IsBackground

 

Свойство. Работа в фоновом режиме. GC работает как фоновый

 

 

поток.

 

 

 

 

 

Name

 

Свойство. Дружественное текстовое имя потока. Если поток никак

 

 

не назван – значение свойства установлено в null.

 

 

 

Поток может быть поименован единожды. Попытка переименования

 

 

потока возбуждает исключение.

 

 

 

Priority

 

Свойство. Значение приоритета потока. Область значений –

 

 

значения перечисления ThreadPriority.

 

 

ThreadState

 

Свойство. Состояние потока. Область значений – значения

 

 

перечисления ThreadState.

 

 

 

Interrupt()

 

Прерывание работы текущего потока.

 

 

Join()

 

Ожидание

появления

другого

потока

(или

определённого

 

 

промежутка времени) с последующим завершением.

 

Resume()

 

Возобновление выполнения потока после приостановки.

Start()

 

Начало выполнения ранее созданного потока, представленного

 

 

делегатом класса ThreadStart.

 

 

 

Suspend()

 

Приостановка выполнения потока.

 

 

 

Abort()

 

Завершение выполнения потока посредством генерации исключения

 

 

TreadAbortException в останавливаемом потоке. Это исключение

 

 

следует перехватывать для продолжения выполнения оставшихся

 

 

потоков приложения. Перегруженный вариант метода содержит

 

 

параметр типа object. An object that contains application-

 

 

specific information, such as state, which can be used by the

 

 

thread being aborted.

 

 

 

 

Именование потока

Потоки рождаются безымянными. Это означает, что у объекта, представляющего поток, свойство Name имеет значение null. Ничего страшного. Главный поток всё равно изначально поименовать некому. То же самое и с остальными потоками. Однако никто не может помешать потоку поинтересоваться своим именем. И получить имя. Несмотря на то, что это свойство при выполнении приложения играет вспомогательную роль, повторное переименование потоков недопустимо. Повторное изменение значения свойства Name приводит к возбуждению исключения.

using System;

using System.Threading;

namespace ThreadApp_1

{

class StartClass

{

static void Main(string[] args) {//================================================================== int i = 0;

bool isNamed = false; do

{

139


try

{

if (Thread.CurrentThread.Name == null)

{

Console.Write(“Get the name for current Thread > “); Thread.CurrentThread.Name = Console.ReadLine();

}

else

{

Console.WriteLine(“Current Thread : {0}.”, Thread.CurrentThread.Name); if (!isNamed)

{

Console.Write(“Rename it. Please...”); Thread.CurrentThread.Name = Console.ReadLine();

}

}

}

catch (InvalidOperationException e)

{

Console.WriteLine(“{0}:{1}”,e,e.Message); isNamed = true;

}

i++;

}

while (i < 10);

}//==================================================================

}

}

Игры с потоками

Но сначала о том, что должно происходить в потоке. Выполнение текущего потока предполагает выполнение программного кода.

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

Точкой входа ПЕРВИЧНОГО потока являются СТАТИЧЕСКИЕ функции Main или WinMain. Точнее, первый оператор метода.

Точка входа ВТОРИЧНОГО потока назначается при создании потока.

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

неперехваченное исключение,

не будет достигнут конец цепочки операторов (последний оператор в функциях

Main или WinMain),

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

Всилу того, что первичный поток создаётся и запускается автоматически (без

какого-либо особого участия со стороны программиста), то и

заботиться в

случае простого однопоточного приложения не о чем.

о создании

дополнительных

При создании многопоточного приложения забота

потоков – забота программиста. Здесь всё надо делать своими руками. Деятельность по созданию потока предполагает три этапа:

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

создание объекта-представителя специального класса-делегата (ThreadStart class), который настраивается на точку входа в поток,

создание объекта-представителя класса потока. При создании объекта потока конструктору потока передаётся в качестве параметра ссылка на делегата,

настроенного на точку входа.

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

140