Файл: 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