Цель работы: получить практические навыки создания многопоточных приложений, используя классы библиотеки FCL.
Задачи работы:
– изучить технологию создания многопоточных приложений
в среде разработки Visual Studio платформы .NET;
– изучитьосновные классы библиотеки FCL, предназначенные для создания многопоточных приложений.
– выполнить практическое задание по разработке приложения на языке С#.
Краткие теоретические сведения
С помощью языка C# можно создавать приложения, которые выполняют несколько задач одновременно, при этом задачи, которые могут потенциально задержать выполнение других задач, выполняются в отдельных потоках. Такой способ организации работы прило-жения называется многопоточностью, или свободным созданием
потоков.
Поток (thread) можно представить как специфический путь выполнения внутри процесса Win32.
Многопоточность – это свойство платформы или приложения, состоящее в том, что процесс, порожденный в операционной системе, может состоять из нескольких потоков, выполняющихся параллельно, т. е. без предписанного порядка во времени. Такие потоки также называют потоками выполнения (от англ. thread of execution), иногда – нитями (буквальный перевод слова thread) или тредами.
Процесс – это объект, который создается операционной системой для каждого приложения в момент его запуска. Процесс характеризуется собственным адресным пространством, которое недоступно другим процессам напрямую.
Сутью многопоточности является квазимногозадачность на уровне одного исполняемого процесса, т. е. выполнение всех потоков в адресном пространстве процесса. Кроме того, все потоки процесса имеют не только общее адресное пространство, но и общие дескрипторы файлов. Выполняющийся процесс имеет как минимум один –главный – поток.
Первый поток, создаваемый в процессе, называется первичным (primary thread). В любом процессе существует по крайней мере один поток, который выполняет роль точки входа для приложения. В приложениях .NET такой точкой входа является метод Main().
Многопоточные приложения создаются для достижения следующих целей:
– повышения производительности работы приложения;
– упрощения программы за счет использования общего адресного пространства;
– сокращения времени отклика приложения.
Примерами приложений, в которых целесообразно создавать дополнительные потоки, могут быть печать большого файла, длительный поиск в файле, выполнение большого объема вычислений, подключение к удаленному серверу.
Класс System.Threading.Thread. Первичный поток в приложении создается автоматически. Базовым классом для создания вторичных потоков является класс Thread, определенный впространстве имен System.Threading и содержащий ряд методов для работы с потоками (табл. 9.1).
Работа с вторичными потоками в приложении состоит из следующих шагов:
– создания потока. Новый поток формируется путем объявления переменной типа Thread и вызова конструктора, которому предо-ставляется имя процедуры или метода, которые требуется выполнить в потоке. На этот метод накладываются некоторые ограничения: он не должен возвращать значение, отличное от void,и не должен принимать параметров;
– запуска потока на выполнение с помощью метода Start.
Таблица 9.1
Методы класса Thread
Метод | Результат |
Start | Запускает поток |
Sleep | Приостанавливает поток на определенное время |
Suspend | Приостанавливает поток, когда он достигает безопасной точки |
Abort | Останавливает поток, когда он достигает безопасной точки |
Resume | Возобновляет работу приостановленного потока |
Join | Приостанавливает текущий поток до тех пор, пока не будет завершен другой поток. При заданном времени ожидания этот метод возвращает значение True при условии окончания другого потока в течение этого времени |
Потоку можно присвоить имя, используя свойство Name. Это создает большие удобства при отладке, так как имена потоков можно вывести или увидеть в окне Debug–Threads среды Visual Studio. Имя потоку может быть назначено в любой момент, но только один раз, поскольку при попытке его изменения будет сгенерировано исключение.
Главному потоку приложения также можно назначить имя.
Пример консольного приложения, в котором главному и вторичному потоку присвоены имена, представлен в листинге 9.1. В этом примере доступ к главному потоку осуществляется через статическое свойство CurrentThread класса Thread.
Листинг 9.1. Присваивание имен главному и вторичному потокам
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
Namespace поток1
{
Class Program
{
Static void Main()
{
// Присваивание имени main главному потоку,
// создаваемому автоматически
Thread.CurrentThread.Name = "main";
// Создание объекта worker вторичного потока. Конструктору класса
// Thread передается имя функции Go, которая будет выполняться в потоке
Thread worker = new Thread(Go);
// Присваивание имени worker вторичному потоку
worker.Name = "worker";
// Запуск вторичного потока на выполнение
worker.Start();
Go(); // Вызов функции для вывода имен запущенных потоков
Console.ReadLine();
}
// Функция, которая выполняется в потоке
Static void Go()
{
Console.WriteLine("Hello from " + Thread.CurrentThread.Name);
}
}
}
Результатом работы этой программы являются строки
Hello from main
Hello from worker
Основные и фоновые потоки. Выделяют два типа потоков:
основные и фоновые.
Основные потоки характеризуются тем, что они не дают приложению завершиться, пока не завершатся сами. По умолчанию потоки создаются как основные, что означает, что приложение не будет завершено, пока один из таких потоков будет исполняться.
Пример разработки интерфейса приложения Windows Forms, имитирующего процесс форматирования диска, выполняемый в основном потоке, показан на рис. 9.1, а его код приведен в листинге 9.2. После запуска этого приложения мы сможем закрыть главное окно приложения во время форматирования, однако выполнение потока при этом не будет завершено, поэтому уже после закрытия окна приложения мы увидим сообщение о том, что форматирование завершено.
Фоновые потоки завершаются сразу после закрытия прило-жения.
|
|
![](https://pdnr.ru/poisk-ruru/baza26/14061526358147.files/image069.jpg)
Рис. 9.1. Интерфейс приложения, имитирующего
процесс форматирования диска
Листинг 9.2. Код формы приложения, имитирующего процесс форматирования диска (созданный поток является основным)
// Эта строка добавляется вручную
using System.Threading;