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

Лабораторные работы / Метода по 2 лабе

.pdf
Скачиваний:
0
Добавлен:
29.09.2026
Размер:
988 Кб
Скачать
☆
Лабораторная работа
Управление процессами и потоками в
Microsoft Windows
Методические указания
1 Цель работы
Получение навыков практической работы в операционной системе Microsoft Windows. Изучение основных способов создания и порождения процессов и потоков в операционной системе Windows.
2 Процессы
При запуске приложения операционная система создает для него отдельный процесс, которому выделяется определённое адресное пространство в памяти и который изолирован от других процессов. Процесс, как минимум, содержит один основной поток. Вместе с основным потоком переднего плана процесс может создать один или несколько потоков для выполнения части программного кода, связанного с процессом. Эти потоки могут выполняться как на переднем плане, так и в фоновом режиме.
В .NET процесс представлен классом Process из пространства имен
System.Diagnostics. Этот класс позволяет управлять уже запущенными
процессами, а также порождать новые. В данном классе определено ряд свойств и методов, позволяющих получать информацию о процессах и управлять ими:
Свойство Handle: возвращает дескриптор процесса;  Свойство Id: получает уникальный идентификатор процесса в рамках
текущего сеанса ОС;
Свойство MachineName: возвращает имя устройства, на котором запущен
процесс;
Свойство Modules: получает доступ к коллекции
ProcessModuleCollection, которая хранит набор модулей (файлов dll и exe),
загруженных в рамках данного процесса;
Свойство ProcessName: возвращает имя процесса, которое нередко
совпадает с именем приложения;
Свойство StartTime: возвращает время, когда процесс был запущен;  Свойство VirtualMemorySize64: возвращает объем памяти, который
выделен для данного процесса;
Метод CloseMainWindow(): закрывает окно процесса, который имеет
графический интерфейс;
Метод GetProcesses(): возвращающий массив всех запущенных
процессов;
Метод GetProcessesByName(): возвращает процессы по его имени. Так
как можно запустить несколько копий одного приложения, то возвращает массив;
Метод Kill(): останавливает процесс;  Метод Start(): запускает новый процесс.
Получим все запущенные процессы:
foreach(Process process in Process.GetProcesses())
{
// выводим id и имя процесса
Console.WriteLine($"ID: {process.Id} Name: {process.ProcessName}");
}
Получим id процесса, представляющего Visual Studio:
Process proc = Process.GetProcessesByName("devenv")[0];
Console.WriteLine($"ID: {proc.Id}");
2.1 Порождение нового процесса
Простейший способ породить новый процесс — воспользоваться статическим методом Start(), определенным в классе Process. Ниже приведена одна из самых простых форм этого метода:
public static Process Start(string имя_файла)
где имя_файла обозначает конкретное имя файла, который должен исполняться или же связан с исполняемым файлом.
Когда созданный процесс завершается, следует вызвать метод Close(), чтобы освободить память, выделенную для этого процесса. Ниже приведена форма объявления метода Close().
public void Close()
Для того чтобы организовать ожидание завершения процесса, можно воспользоваться методом WaitForExit(). Ниже приведены две его формы.
public void WaitForExit()
public bool WaitForExit(int миллисекунд)
В первой форме ожидание продолжается до тех пор, пока процесс не завершится, а во второй форме — только в течение указанного количества миллисекунд. В последнем случае метод WaitForExit() возвращает логическое значение true, если процесс завершился, и логическое значение false, если он все еще выполняется.
В приведенном ниже примере программы демонстрируется создание, ожидание и закрытие процесса. В этой программе сначала запускается стандартная сервисная программа Windows: текстовый редактор NotePad.exe, а затем организуется ожидание завершения программы NotePad как процесса.
Пример 1.
Чтобы отделить настройку параметров запуска от самого запуска можно использовать класс ProcessStartInfo:
ProcessStartInfo procInfo = new ProcessStartInfo();
// исполняемый файл программы - браузер Chrome
procInfo.FileName = "C://Program Files (x86)//Google//Chrome//Application//chrome.exe";
// аргументы запуска - адрес интернет-ресурса
procInfo.Arguments = "http://google.com";
Process.Start(procInfo);
2.2 Потоки процесса
Поток — это основная единица, которой операционная система выделяет время процессора. Каждый поток имеет приоритет планирования и набор структур, в которых система сохраняет контекст потока, когда выполнение потока приостановлено. Все потоки процесса используют общий диапазон виртуальных адресов. Поток может исполнять любую часть программного кода, включая части, выполняемые в данный момент другим потоком.
Если программа выполняет операции, которые могут выполняться параллельно, можно уменьшить общее время выполнения путем выполнения этих операций в отдельных потоках и запуска программы в многопроцессорной или многоядерной системе. В такой системе использование многопоточности может увеличить пропускную способность, а также повысить скорость реагирования.
Свойство Threads представляет коллекцию потоков процесса - объект
ProcessThreadCollection, каждый поток в которой является объектом ProcessThread. В данном классе можно выделить следующие свойства:
CurrentPriority: возвращает текущий приоритет потока;  Id: идентификатор потока;  IdealProcessor: позволяет установить процессор для обработки потока;  PriorityLevel: уровень приоритета потока;  StartAddress: адрес в памяти функции, запустившей поток;  StartTime: время запуска потока.
Пример 2.
Получение идентификаторов и времени запуска всех потоков процесса Crome:
3 Потоки
Основной функционал для использования потоков в приложении сосредоточен в пространстве имен System.Threading. В нем определен класс, представляющий отдельный поток - класс Thread.
Класс Thread определяет ряд методов и свойств, которые позволяют управлять потоком и получать информацию о нем. Основные свойства класса:
Статическое свойство CurrentContext позволяет получить контекст, в
котором выполняется поток;
Статическое свойство CurrentThread возвращает ссылку на
выполняемый поток;
Свойство IsAlive указывает, работает ли поток в текущий момент;  Свойство IsBackground указывает, является ли поток фоновым;  Свойство Name содержит имя потока;
Свойство Priority хранит приоритет потока - значение перечисления
ThreadPriority;
Свойство ThreadState возвращает состояние потока - одно из значений
перечисления ThreadState.
Некоторые методы класса Thread:
Статический метод GetDomain возвращает ссылку на домен приложения;  Статический метод GetDomainID возвращает id домена приложения, в
котором выполняется текущий поток;
Статический метод Sleep останавливает поток на определенное
количество миллисекунд;
Метод Abort уведомляет среду CLR о том, что надо прекратить поток,
однако прекращение работы потока происходит не сразу, а только тогда, когда это становится возможно. Для проверки завершенности потока следует опрашивать его свойство ThreadState;
Метод Interrupt прерывает поток на некоторое время;  Метод Join блокирует выполнение вызвавшего его потока до тех пор, пока
не завершится поток, для которого был вызван данный метод;
Метод Start запускает поток.
Пример 3.
Используем вышеописанные свойства и методы для получения информации о потоке:
В этом случае получим примерно следующий вывод:
Так как по умолчанию свойство Name у объектов Thread не установлено, то в первом случае получаем в качестве значения этого свойства пустую строку.
Статус потока
Статусы потока содержатся в перечислении ThreadState:
Aborted: поток остановлен, но пока еще окончательно не завершен;  AbortRequested: для потока вызван метод Abort, но остановка потока
еще не произошла;
Background: поток выполняется в фоновом режиме;  Running: поток запущен и работает (не приостановлен);  Stopped: поток завершен;
StopRequested: поток получил запрос на остановку;  Suspended: поток приостановлен;  SuspendRequested: поток получил запрос на приостановку;  Unstarted: поток еще не был запущен;  WaitSleepJoin: поток заблокирован в результате действия методов
Sleep или Join.
В процессе работы потока его статус многократно может измениться под действием методов.
Приоритеты потоков
Приоритеты потоков располагаются в перечислении ThreadPriority:
Lowest BelowNormal Normal AboveNormal Highest
По умолчанию потоку задается значение Normal. Однако мы можем изменить приоритет в процессе работы программы. Например, повысить важность потока, установив приоритет Highest. Среда CLR будет считывать и анализировать значения приоритета и на их основании выделять данному потоку то или иное количество времени.
3.1 Создание потоков
Создание нового объекта Thread приводит к созданию нового потока. Класс
Thread имеет конструкторы, которые принимают делегат ThreadStart или ParameterizedThreadStart. Этот делегат инкапсулирует метод, который
вызывается новым потоком при вызове метода Start.
Метод Start завершается немедленно, часто даже до запуска нового потока. Можно использовать свойства ThreadState и IsAlive, чтобы определить состояние потока в настоящий момент, но эти свойства ни в коем случае нельзя использовать для
синхронизации действий потоков.
Примечание
После запуска потока не нужно сохранять ссылку на объект Thread. Поток продолжит выполняться, пока не завершится запущенная в нем процедура.
Пример 4.
Здесь новый поток будет производить действия, определенные в методе Count.
Чтобы запустить этот метод в качестве второго потока, мы сначала создаем объект потока:
Thread myThread = new Thread(new ThreadStart(Count));
В конструктор передается делегат ThreadStart, который в качестве параметра принимает метод Count. И следующей строкой myThread.Start() запускаем поток. И после с помощью метода Thread.Sleep мы усыпляем поток на 400 миллисекунд. После этого управление передается главному потоку, и выполняются все остальные действия, определенные в методе Main.
Таким образом, в программе будут работать одновременно главный поток, представленный методом Main, и второй поток. Как только все потоки отработают, программа завершит свое выполнение.
Подобным образом можно создать и три, и четыре, и целый набор новых потоков, которые смогут решать те или иные задачи.
Существует еще одна форма создания потока:
Thread myThread = new Thread(Count);
Хотя в данном случае явным образом не используется делегат ThreadStart, но неявно он создается. Компилятор C# выводит делегат из сигнатуры метода Count и вызывает соответствующий конструктор.
3.2 Передача данных в потоки
На платформе .NET Framework версии 2.0 делегат ParameterizedThreadStart предоставляет простой способ передать в поток объект с данными при вызове перегрузки метода Thread.Start.
Пример 5.
Делегат ParameterizedThreadStart не является типобезопасным способом передачи данных, так как перегруженный метод Thread.Start принимает любой объект. Вместо этого можно инкапсулировать процедуру потока и данные во вспомогательный класс и выполнять процедуру потока при помощи делегата
ThreadStart.
Ни один из делегатов ThreadStart или ParameterizedThreadStart не имеет возвращаемого значения, так как им некуда возвращать данные после асинхронного вызова. Чтобы получить результаты из метода потока, можно использовать метод обратного вызова.
4 Содержание отчета по лабораторной работе
Отчет по лабораторной работе должен содержать следующие сведения:
цель работы;
примеры выполнения команд; пояснительные комментарии к командам.