Многопоточность в языке программирования C#

MULTITREADING IN THE C# PROGRAMMING LANGUAGE Deniskin A.

'Денискин Александр Владимирович /Deniskin Aleksandr Vladimirovich - студент, кафедра автоматизированных систем обработки информации и управления, Институт электроники и светотехники, Мордовский государственный университет им. Н. П. Огарева, г. Саранск

Abstract: this article discusses the C # language such as multithreading feature. Article explains reasons why you need to use it, under what conditions multithreading helps to optimize the application and why using multithreading is so effective. It describe the general principles of multi-threading, how to use C # System. Threading library to generate code that uses multiple threads. Shows an example of the use of multithreading in the program. It is told how to use multithreading for application acceleration.

Аннотация: в данной статье рассматривается такое свойство языка C# как многопоточность. Объясняется, для чего необходимо её использовать, при каких условиях она помогает в оптимизации приложений и почему она так эффективна. Описываются общие принципы работы многопоточности, способы использования библиотеки C# System. Threading для создания кода, в котором используется несколько потоков. Демонстрируется пример применения многопоточности в программе. Рассказывается, как использовать многопоточность для ускорения работы приложений.

Keywords: thread, multithreading, process, C#, syntax, function.

Ключевые слова: поток, многопоточность, процесс, C#, синтаксис, функция.

Язык C# может используется для написания пользовательских программ, при этом достаточно часто возникает необходимость обращаться к устройствам ввода-вывода, базам данных, либо к сетевым ресурсам [1]. Эффективно решать подобные задачи позволяет многопоточность.

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

Поток (thread) представляет собой независимую последовательность инструкций в программе. В приложениях, которые имеют пользовательский интерфейс, всегда есть как минимум один главный поток, который отвечает за состояние компонентов интерфейса. Кроме него в программе может создаваться множество независимых дочерних потоков, которые будут выполняться независимо [2].

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

В качестве примера рассмотрим простую «пинговалку» - программу, которая определяет действующие компьютеры в подсети. Делаем это следующим образом: компьютеры, входящие в одну подсеть, принадлежат одному диапазону IP адресов, адрес заканчивающийся нулём является адресом подсети, а заканчивающийся числом 255 является широковещательным адресом данной сети. Адреса в диапазоне от 1 до 254 включительно являются полноправными адресами хостов внутри подсети, их можно использовать для назначения на компьютерах, поэтому считываем адрес сети,

заменяем последнюю цифру 0 на число от 1 до 254, чтобы получить адрес, который может иметь компьютер выбранной подсети:

static void Main

{

//Создаём объект Ping

System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping();

//Считываем адрес подсети

string str=Console.ReadLine(); str=str. Substring(0,str.Length-1);

//Проверяем все адреса сети

for (int i = 1; i < 255; ++i) {

System.Net.NetworkInformation.PingReply pingReply =

ping.Send(str+i, 1000); if (pingReply.Status.ToString().Equals("Success")) Console.WriteLine(str + i);

}

}

Эта программа работает и действительно выводит адреса всех подключенных компьютеров, ведь она проверяет весь диапазон IP адресов подсети на доступность. Однако, таких адресов 254 и для каждого программа ждёт отклика в течении секунды. Очевидно, что независимо от мощности процессора время выполнение такой программы может составлять до 254 секунд. Для пользовательского приложения такое недопустимо. Здесь нам и приходит на помощь многопоточность.

Мы можем пинговать каждый компьютер параллельно, разделив процесс выполнения на 254 потоков. Для этого мы будем использовать встроенную в C# библиотеку System.Threading. Чтобы запустить новый поток нам сначала необходимо его создать и передать ему на выполнение функцию, возвращающую void. В простейшем виде создание потока выглядит так:

static void Main

{

//Создаем объект потока

Thread thread = new Thread(ThreadFunction);

//Запускаем поток

thread.Start();

}

//Функция потока

static void ThreadFunction

{

//Код функции

}

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

Некоторые методы класса Thread:

1. Статический метод Sleep останавливает поток на определенное количество миллисекунд.

2. Метод Abort уведомляет среду CLR о том, что надо прекратить поток.

3. Метод Interrupt прерывает поток на некоторое время.

22

4. Метод Join блокирует выполнение вызвавшего его потока до тех пор, пока не завершится поток, для которого был вызван данный метод.

5. Метод Resume возобновляет работу ранее приостановленного потока.

6. Метод Start запускает поток.

7. Метод Suspend приостанавливает поток [3].

Метод Start() имеет возможность передавать объект с данными, используемыми функцией в потоке. Обратите внимание, что мы можем создать функцию только с одним аргументом и только типа object, даже если он является объектом int, как в нашем случае. Таким образом мы можем создать функцию с параметром и автоматически в цикле параллельно запускать функции с разными данными:

static string str;

static void Main(string[] args) {

str=Console.ReadLine() ; str=str.Substring(0,str.Length-1);

for (int i = 1; i < 255; ++i) {

//Создаём поток Thread thread = new Thread(Function); //Запускаем поток

thread.Start(i);

}

}

//Создаём отдельную функцию для запроса

static void Function(object i) {

System.Net.NetworkInformation.Ping ping = new System.Net.NetworkInformation.Ping(); System.Net.NetworkInformation.PingReply pingReply = ping.Send(str + i, 1000);

if

Console.WriteLine(str + i);

}

Такая программа выполняется почти мгновенно. Что же произошло? Процессор очень быстро создал множество потоков, каждый из которых начал выполняться сразу же после создания, отправил запрос по адресу и получил ответ, не задерживая другие потоки. То есть при помощи использования многопоточности мы ускорили выполнение программы в 254 раз. Потрясающий результат! А если представить, что необходимо работать с огромной базой данных, и множество раз запрашивать данные, пока пользователь работает с программой, становится очевидно, что без разделения работы не обойтись. Многопоточность незаменима тогда, когда необходимо, чтобы графический интерфейс продолжал отзываться на действия пользователя во время выполнения некоторой обработки информации, либо когда программа выполняет множество действий, для которых требуются данные из сторонних источников. Таким образом, использование многопоточности в программировании является не просто методом оптимизации, а необходимостью.

Литература

1. Александров Э. Э., Афонин В. В. Программирование на языке С в Microsoft Visual Studio 2010. [Электронный ресурс]. Режим доступа: http://www.intuit.ru/department/ pl/prcmsvs2010/ (дата обращения: 01.11.2015).

23

2. Александров Э. Э., Афонин В. В. Введение в программирование в языке С. Саранск: Мордовский гос. университет им. Н. П. Огарева, 2009.

3. Джеффри Рихтер. CLR via C#. Программирование на платформе Microsoft. NET Framework 4.5 на языке C#. 4-е изд. СПб.: Питер, 2013.

РАСЧЕТ ОПЕРАЦИОННЫХ ХАРАКТЕРИСТИК МНОГОКАНАЛЬНОЙ СИСТЕМЫ МАССОВОГО ОБСЛУЖИВАНИЯ С ОТКАЗАМИ Денискин А. В.

Денискин Александр Владимирович /Deniskin Aleksandr Vladmirovich - студент, кафедра автоматизированных систем обработки информации и управления, Институт электроники и светотехники, Мордовский государственный университет им. Н. П. Огарева, г. Саранск

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

Ключевые слова: моделирование систем, системы массового обслуживания, формулы Эрланга, 0#.

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

Предназначение СМО состоит в обслуживании потока заявок (требований), представляющих последовательность событий, поступающих нерегулярно и в заранее неизвестные и случайные моменты времени. Обслуживание заявок также имеет непостоянный характер, происходит в случайные промежутки времени и зависит от многих и даже неизвестных причин. Случайный характер потока заявок и времени их обслуживания обусловливает неравномерность загрузки СМО: на входе могут накапливаться необслуженные заявки (перегрузка СМО) либо заявок нет или их меньше, чем свободных каналов (недогрузка СМО). Эффективность функционирования СМО определяется ее пропускной способностью — относительным числом обслуженных заявок. По числу каналов п все СМО разделяются на одноканальные (п=1) и многоканальные (п > 1).

По числу мест для ожидания обслуживания различаются три класса СМО.

1. СМО с отказами (нулевое ожидание или явные потери). «Отказная» заявка вновь поступает в систему, чтобы ее обслужили.

2. СМО с ожиданием (неограниченное ожидание или очередь). При занятости всех каналов заявка поступает в очередь и, в конце концов, будет выполнена.

3. СМО смешанного типа (ограниченное ожидание). Имеется ограничение на длину очереди (сервис по обслуживанию автомобилей). Другой вид ограниченного ожидания — ограничение на время пребывания заявки в СМО.

Для обозначения различных систем обслуживания принята кодировка Кендалла: А|В|п|ш. В этой записи символ А - код функции распределения случайной длины интервала между соседними требованиями входного потока; символ В - код функции распределения случайного времени обслуживания каким-либо прибором в системе; п - число обслуживающих приборов в системе; ш - число мест в системе для ожидания. Если число мест для ожидания не ограничено (ш = да), то кодировка Кендалла