Главная » Просмотр файлов » Учебное пособие

Учебное пособие (1077022), страница 24

Файл №1077022 Учебное пособие (Самохвалов Э.Н., Ревунков Г.И., Гапанюк Ю.Е. - Введение в проектирование и разработку Интернет-приложений) 24 страницаУчебное пособие (1077022) страница 242018-01-10СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 24)

Внастоящее время именно этот класс является рекомендуемым средствомдля работы с потоками. Класс Task основан на классе ThreadPool, онобладает всеми достоинствами ThreadPool, и при этом содержит удобныйдля прикладного программиста набор методов для работы с потоками.193В данном разделе представлены примеры работы с классами Thread иTask (класс ThreadPool не рассматривается), а также пример параллельногопоиска в массиве данных на основе класса Task.9.1 Использование класса ThreadПример использования класса Thread:/// <summary>/// Пример запуска потоков/// </summary>public static void ThreadExample(){Console.WriteLine("Пример использования \"старого\" вариантамногопоточности с использованием класса Thread:");const int n = 10;Thread[] threads = new Thread[n];for (int i = 0; i < n; i++){threads[i] = new Thread(ThreadRun);}for (int i = 0; i < n; i++){threads[i].Start("Поток №" + i.ToString());}}В данном примере создается массив из 10 элементов threads объектовкласса Thread.

В цикле проводится инициализация элементов массива, длячего и создаются объекты класса Thread.Конструктор класса Thread принимает параметр делегатного типа,который соответствует делегату ParameterizedThreadStart:public delegate void ParameterizedThreadStart(object obj);Это означает, что в конструктор класса Thread нужно передать метод,который принимает один параметр типа object и возвращает void. Вданном примере таким методом будет ThreadRun.Далее в цикле запускаются потоки.

Для этого вызывается метод Startдля каждого из элементов массива потоков. В качестве параметра в методStart передается объект класса object, который подставляется при запуске194потока в делегатный параметр ParameterizedThreadStart. В нашем примерестрока «"Поток №" + i.ToString()» будет передана в качестве параметраметоду ThreadRun.Рассмотрим более детально метод ThreadRun, который вызывается впотоке:/// <summary>/// Метод, запускаемый в потоке/// </summary>/// <param name="param"></param>public static void ThreadRun(object param){Random r = new Random();int delay = r.Next(3000, 10000);Thread.Sleep(delay);Console.WriteLine(param.ToString());}В методе создается объект r класса Random, применяющийся длягенерации случайных чисел.

Метод r.Next возвращает случайное число вдиапазоне от 3000 до 10000 – это задержка в миллисекундах, котораясоответствует диапазону от 3 до 10 секунд.Полученное случайное время задержки передается в качествепараметра статическому методу Thread.Sleep, выполняющему задержкутекущего потока на заданное количество миллисекунд.После задержки в консоль выводится сообщение, переданное в методThreadRun в качестве параметра.Таким образом, параллельно запускаются 10 экземпляров методаThreadRun, каждый из которых через случайное время в диапазоне от 3 до10 секунд выводит в консоль сообщение, переданное в метод в качествепараметра при инициализации потока.Результаты вывода в консоль (после завершения работы всехпотоков):Примериспользованиякласса Thread:Поток №7Поток №8"старого"вариантамногопоточностисиспользованием195Поток №9Поток №5Поток №6Поток №1Поток №0Поток №2Поток №3Поток №4Сообщения выводятся в консоль в случайном порядке, что связано сослучайным временем задержки в каждом потоке.Отметим, что, хотя класс Thread позволяет успешно решать задачупараллельногозапускапотоков,егоиспользованиесвязаносопределенными неудобствами для прикладного программиста.

Всепараметры передаются в метод потока через единственный параметр типаobject. Поэтому, как правило, необходимо создавать отдельный класс,который будет содержать как входные, так и выходные параметры потока,передавать объект данного класса в качестве параметра в метод потока, вметоде потока осуществлять приведение типа к требуемому классу, ивозвращать через данный класс результаты работы потока, так как классThread не имеет специальных способов возврата результатов работы ввызывающий поток.Также следует отметить, что аналогичные затруднения возникают прииспользовании класса ThreadPool.9.2 Использование класса TaskРазработчики .NET учли рассмотренные выше сложности припроектировании класса Task.Реализуем рассмотренный ранее пример с использованием классаTask:/// <summary>/// Пример запуска потоков с использованием Task/// </summary>public static void TaskExample()196{Console.WriteLine("Пример использования \"нового\" вариантамногопоточности с использованием класса Task:");const int n = 10;for (int i = 0; i < n; i++){Task.Factory.StartNew((object param) =>{Random r = new Random();int delay = r.Next(3000, 10000);Thread.Sleep(delay);Console.WriteLine(param.ToString());},"Поток №" + i.ToString());}}В данном примере не нужно создавать массив.

Класс Task имеетстатическое свойство Factory («фабрика»). Здесь предполагается, что это«фабрика» для создания объектов (применяется шаблон объектноориентированного проектирования «фабрика»). У «фабрики» есть методсоздания и запуска потока StartNew. В данном примере используетсяследующая перегрузка метода StartNew:public Task StartNew(Action<object> action, object state);ПервымпараметромметодаStartNewявляетсяметод,соответствующий делегату Action<object>, то есть, как и в случаеиспользования класса Thread метод принимающий параметр типа object ивозвращающий void.В рассматриваемом примере первому параметру соответствуетлямбда-выражение, представляющее собой аналог метода ThreadRun прииспользовании класса Thread:(object param) =>{Random r = new Random();int delay = r.Next(3000, 10000);Thread.Sleep(delay);Console.WriteLine(param.ToString());}197Второй параметр метода StartNew – параметр типа object, который призапуске потока подставляется в делегатный параметр.

Здесь второмупараметру соответствует строка «"Поток №" + i.ToString()», которая призапуске потока подставляется в параметр лямбда-выражения «(objectparam) => ».Результаты вывода в консоль (после завершения работы всехпотоков):Примериспользования"нового"вариантамногопоточностисиспользованиемкласса Task:Поток №0Поток №5Поток №1Поток №3Поток №2Поток №7Поток №6Поток №4Поток №9Поток №8Как и в предыдущем случае сообщения выводятся в консоль вслучайном порядке.Код решения задачи с использованием класса Task получился болеекомпактным, метод потока задается с помощью лямбда-выражения.Однако более важное преимущество класса Task – возможность возвратарезультата выполнения потока.9.3 Возвратрезультатавыполненияпотокасиспользованием класса TaskРешим более сложную задачу с применением класса Task.

Заполниммассив числами от 1 до 100 и найдем в нем числа, которые без остаткаделятся на 3. При этом массив разделим на 10 подмассивов (посоответствующим десяткам) и будем выполнять поиск многопоточно.198Результаты поиска по 10 подмассивам объединим в единый массиврезультатов.Для решения данной задачи необходимо решить подзадачу несвязанную с потоками – разделение массива на подмассивы, для чегосоздадим вспомогательный класс для хранения диапазонов:/// <summary>/// Хранение минимального и максимального значений диапазона/// </summary>public class MinMax{public int Min {get; set;}public int Max {get; set;}public MinMax(int pmin, int pmax){this.Min = pmin;this.Max = pmax;}}Разделение массива на подмассивы реализуется с помощью методаDivideSubArrays статического класса SubArrays.

Код приведен ниже идетально откомментирован:/// <summary>/// Класс для деления массива на последовательности/// </summary>public static class SubArrays{/// <summary>/// Деление массива на последовательности/// </summary>/// <param name="beginIndex">Начальный индекс массива</param>/// <param name="endIndex">Конечный индекс массива</param>/// <param name="subArraysCount">Требуемое количествоподмассивов</param>/// <returns>Список пар с индексами подмассивов</returns>public static List<MinMax> DivideSubArrays(int beginIndex, int endIndex, int subArraysCount){//Результирующий список пар с индексами подмассивовList<MinMax> result = new List<MinMax>();//Если число элементов в массиве слишком мало для деления//то возвращается массив целикомif ((endIndex - beginIndex) <= subArraysCount)199{result.Add(new MinMax(0, (endIndex - beginIndex)));}else{//Размер подмассиваint delta = (endIndex - beginIndex) / subArraysCount;//Начало отсчетаint currentBegin = beginIndex;//Пока размер подмассива укладывается в оставшуюся//последовательностьwhile ((endIndex - currentBegin) >= 2 * delta){//Формируем подмассив на основе начала//последовательностиresult.Add(new MinMax(currentBegin, currentBegin + delta));//Сдвигаем начало последовательности//вперед на размер подмассиваcurrentBegin += delta;}//Оставшийся фрагмент массиваresult.Add(new MinMax(currentBegin, endIndex));}//Возврат списка результатовreturn result;}}В результате работы метод DivideSubArrays возвращает списокобъектов класса MinMax, которые хранят начальный и конечный индексысоответствующих диапазонов массива.На этом рассмотрение вспомогательных классов завершено, и мыпереходимкметодуArrayThreadExample,осуществляющемумногопоточный поиск в массиве:/// <summary>/// Многопоточный поиск в массиве/// </summary>public static void ArrayThreadExample(int ArrayLength, int ThreadCount, int Divider){//Результирующий список чиселList<int> Result = new List<int>();//Создание и заполнение временного списка данныхList<int> tempList = new List<int>();200for (int i = 0; i < ArrayLength; i++) tempList.Add(i + 1);//Деление списка на фрагменты//для параллельного запуска в потокахList<MinMax> arrayDivList =SubArrays.DivideSubArrays(0, ArrayLength, ThreadCount);int count = arrayDivList.Count;//Вывод диапазонов деления исходного массиваfor (int i = 0; i < count; i++){//Вывод результатов, найденных в каждом потокеConsole.WriteLine("Диапазон " + i.ToString() + ": " +arrayDivList[i].Min + " - " +arrayDivList[i].Max);}Console.WriteLine();//Создание таймераStopwatch timer = new Stopwatch();//Запуск таймераtimer.Start();//Количество потоков соответствует количеству фрагментов массиваTask<List<int>>[] tasks = new Task<List<int>>[count];//Запуск потоковfor (int i = 0; i < count; i++){//Создание временного списка, чтобы потоки//не работали параллельно с одной коллекциейList<int> tempTaskList =tempList.GetRange(arrayDivList[i].Min,arrayDivList[i].Max - arrayDivList[i].Min);tasks[i] = new Task<List<int>>(//Метод, который будет выполняться в потокеArrayThreadTask,//Параметры потока передаются в виде кортежа,//чтобы не создавать временный классnew Tuple<List<int>, int>(tempTaskList, Divider));//Запуск потокаtasks[i].Start();}//Ожидание завершения всех потоковTask.WaitAll(tasks);//Остановка таймера201timer.Stop();//Объединение результатов полученных из разных потоковfor (int i = 0; i < count; i++){//Вывод результатов, найденных в каждом потокеConsole.Write("Поток " + i.ToString() + ": ");foreach (var x in tasks[i].Result)Console.Write(x.ToString() + " ");Console.WriteLine();//Добавление результатов конкретного потока//в общий массив результатовResult.AddRange(tasks[i].Result);}//Вывод общего массива результатовConsole.WriteLine("\nМассив из {0} элементов обработан {1}потоками за {2}.

Найдено: {3}", ArrayLength,count, timer.Elapsed, Result.Count);foreach (int i in Result)Console.Write(i.ToString().PadRight(5));Console.WriteLine();}Метод принимает три параметра: int ArrayLength – число элементов в массиве; в рассматриваемомпримере оно равно 100; int ThreadCount – число потоков для одновременного поиска; врассматриваемом примере составляет 10; int Divider – искомый делитель; в рассматриваемом примереравен 3.В начале работы метода создается переменная Result типа List<int>.

Характеристики

Список файлов книги

Самохвалов Э.Н., Ревунков Г.И., Гапанюк Ю.Е
примеры
01
Structures
Structures
v15
.suo
Structures
Properties
AssemblyInfo.cs
bin
Debug
Structures.exe
Structures.exe.config
Structures.pdb
obj
Debug
TempPE
CoreCompileInputs.cache
DesignTimeResolveAssemblyReferencesInput.cache
Structures.csprojResolveAssemblyReference.cache
Structures.exe
Structures.pdb
TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs
TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs
App.config
Program.cs
Structures.csproj
Свежие статьи
Популярно сейчас
Почему делать на заказ в разы дороже, чем купить готовую учебную работу на СтудИзбе? Наши учебные работы продаются каждый год, тогда как большинство заказов выполняются с нуля. Найдите подходящий учебный материал на СтудИзбе!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
7021
Авторов
на СтудИзбе
260
Средний доход
с одного платного файла
Обучение Подробнее