Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
МУ_ЛР_Технология программирования _ 2.doc
Скачиваний:
14
Добавлен:
26.11.2019
Размер:
654.34 Кб
Скачать

Лабораторная работа № 5. Потоки и процессы в Microsoft Visual Studio.

5.1. Цель работы

Научиться писать многозадачные приложения с использованием средств Microsoft Visual Studio.

5.2. Теоретические сведения

Потоки – это наборы команд, которые могут получать время процессора. Время процессора выделяется квантами. Квант времени – это минимальный ин-

тервал, в течение которого только один поток использует процессор. Как ми- нимум, каждый процесс имеет хотя бы один (главный) поток, но ОС, начиная с Windows95 и NT, позволяют в рамках процесса запустить произвольное число потоков. Существует две модели применения потоков – асимметричная и сим- метричная.

В рамках асимметричной модели потоки решают различные задачи и, как

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

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

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

При работе с потоками могут возникать две следующих проблемы – гон- ки и тупики. Ситуация гонок возникает, когда два или более потока пытаются получить доступ к общему ресурсу и изменить его состояние. Например, По- ток1 получил доступ к ресурсу и изменил его в своих интересах; затем активи-

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

данный момент принадлежит другому потоку. Например, Поток1 захватывает объект А и , для того чтобы продолжить работу, ждет возможности захватить объект Б. В то же время Поток2 захватывает объект Б и ждет возможности за- хватить объект А. Таким образом, оба потока будут заблокированы. Возникно- вения как ситуаций гонок, так и тупиков можно избежать, если пользоваться средствами синхронизации потоков.

Когда создается поток, то ему назначается приоритет, соответствующий

приоритету породившего его процесса. Процессы имеют следующие приорите-

ты – реального времени (Real Time), высокий (High), нормальный (Normal), фо- новый (Idle).

Поддержка многопоточности осуществляется в .NET в основном с помо-

щью пространства имен System.Threading. Некоторые из типов этого про- странства имен приведены в таблице 5.1.

Типы пространства имен System.Threading

Таблица 5.1

Тип

Описание

Interlocked

Класс, обеспечивающий синхронизированный дос-

туп к переменным, которые используются в разных потоках

Monitor

Класс, обеспечивающий синхронизацию доступа к

объектам

Mutex

Класс-примитив синхронизации, который использу-

ется также для синхронизации между процессами

ReaderWriterLock

Класс, определяющий блокировку, поддерживаю-

щую один доступ на запись и несколько – на чтение

Thread

Класс, который создает поток, устанавливает его

приоритет, получает информацию о состоянии

ThreadPool

Класс, используемый для управления набором

взаимосвязанных потоков – пулом потоков

Timer

Класс, определяющий механизм вызова заданного

метода в заданные интервалы времени для пула по- токов

WaitHandle

Класс, инкапсулирующий объекты синхронизации,

которые ожидают доступа к разделяемым ресурсам

IOCompletionalCallback

Класс, получающий сведения о завершении опера-

ции ввода-вывода

ThreadStart

Делегат, представляющий метод, который должен

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

TimerCallback

Делегат, представляющий метод, обрабатывающий

вызовы от класса Timer

WaitCallback

Делегат, представляющий метод для элементов

классов ThreadPool

ThreadPrority

Перечисление, описывающее приоритет потока

ThreadState

Перечисление, описывающее состояние потока

Первичный поток создается автоматически. Для запуска вторичных по- токов используется класс Thread. Основные элементы класса Thread приве- дены в таблице 5.2.

Основные элементы класса Thread

Таблица 5.2

Элемент

Вид

Описание

CurrentThread

Статическое

свойство

Возвращает ссылку на выполняющийся по-

ток (только для чтения)

IsAlive

Свойство

Возвращает true или false в зависимо- сти от того запущен поток или нет

IsBackground

Свойство

Возвращает или устанавливает значение,

которое показывает, является ли этот поток фоновым

Name

Свойство

Установка текстового имени потока

Priority

Свойство

Получить/установить приоритет потока

(используется значение перечисления

ThreadPriority

ThreadState

Свойство

Возвращает состояние потока (использует-

ся значение перечисления ThreadState)

Abort

Метод

Генерирует исключение ThreadAbor- tException. Вызов этого метода обычно завершает работу потока

GetData, SetData

Статические

методы

Возвращает (устанавливает) значение для

указанного слота в текущем потоке

GetDomain, GetDo- mainID

Статические

методы

Возвращает ссылку на домен приложения

(идентификатор домена приложения), в рамках которого работает поток

GetHashCode

метод

Возвращает хеш-код для потока

Sleep

Статический

метод

Приостанавливает выполнение текущего

потока на заданное количество миллисе- кунд

Start

Метод

Начинает выполнение потока, определен-

ного делегатом ThreadStart

Suspend

Метод

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

ли выполнение потока уже приостановле- но, то игнорируется

Resume

Метод

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

потока

Join

Метод

Блокирует вызывающий поток до заверше-

ния другого потока или указанного проме- жутка времени

Interrupt

Метод

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

При создании объекта-потока ему передается делегат, определяющий ме- тод, выполнение которого выделяется в отдельный поток:

Thread t = new Thread (new ThreadStart (имя_метода)); После создания потока заданный метод начинает в нем свою работу, а первичный поток продолжает выполняться. В листинге 5.1 приведен пример

одновременной работы двух потоков.

Листинг 5.1. Создание вторичного потока

using System;

using System.Threading;

namespace ConsoleApplication1

{

class Program

{

static public void Hedgehog()

// метод для вторичного потока

{

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

{

Console.WriteLine(i);Thread.Sleep(1000);

}

}

static void Main()

{

Console.WriteLine("Первичный поток" +

Thread.CurrentThread.GetHashCode());

Thread ta = new Thread(newThreadStart(Hedgehog)); Console.WriteLine("Вторичный поток" +

ta.GetHashCode());

ta.Start();

for (int i = 0; i > -6; --i)

{

Console.Write(" " +i);Thread.Sleep(400);

}

}

}

}

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

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

Листинг 5.2. Потоки, использующие один объект

using System;

using System.Threading;

namespace ConsoleApplication1

{

class Class1

{

public void Do()

{

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

{

Console.Write(" " + i); Thread.Sleep(3);

}

}

}

class Program

{

static void Main()

{

Class1 a = new Class1(); Thread t1=new Thread (new

ThreadStart(a.Do));

t1.Name ="Second"; Console.WriteLine("Поток"+t1.Name); t1.Start();

Thread t2=new Thread (new

ThreadStart(a.Do)); t2.Name="Third"; Console.WriteLine("Поток"+t2.Name); t2.Start();

}

}

}

Для того чтобы блок кода мог использоваться в каждый момент времени

только одним потоком, применяется оператор lock, имеющий следующий формат:

lock (выражение) блок_операторов

Выражение определяет объект, который требуется заблокировать. Для

обычных методов в качестве выражения используется ключевое слово this, для статических – typeof(класс). Блок операторов задает критическую сек- цию кода, которую требуется заблокировать.

5.3. Программа работы

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

1.

1 и 2

6. 2и 13

11. 2 и 11

2.

1 и 3

7. 12 и 13

12. 10 и 11

3.

1 и 12

8. 1 и 14

13. 10 и 12

4.

2 и 12

9. 2 и 15

14. 1 и 12

5. 1 и 13 10. 1 и 11 15. 7 и 13

Метод решения дифференциальных уравнений взять из таблицы 5.3

Таблица 5.3