logo
Лекции по ая

Многопоточность

C# поддерживает параллельное выполнение кода через многопоточность. Поток – это независимый путь исполнения, способный выполняться одновременно с другими потоками.

Программа на C# запускается как единственный поток, автоматически создаваемый CLR и операционной системой (“главный” поток), и становится многопоточной при помощи создания дополнительных потоков. Многопоточность позволяет приложениям разделять задачи и работать над каждой независимо/

Многозадачность - это одновременное исполнение нескольких потоков. Существует два вида многозадачности — совместная (cooperative) и вытесняющая (preemptive). Совместная - каждый поток отвечает за возврат управления процессору, чтобы тот смог обработать другие потоки. Вытесняющая - процессор отвечает за выдачу каждому потоку определенного количества времени, в течение которого поток может выполняться, — кванта времени (timeslice). Далее процессор переключается между разными потоками, выдавая каждому потоку его квант времени, а программист может не заботится о том, как и когда возвращать управление, в результате чего могут работать и другие потоки.

Для работы с многопоточностью среда .NET предоставляет пространство имен System.Threading. В данном пространстве имен содержится огромное количество различных типов, наиболее важны из них класс Thread. У данного класса есть много методов и свойств, например:

Start() - начинает выполнение потока

Suspend() - приостанавливает поток

Resume() - восстанавливает работу потока

Priority - свойство определяющие приоритет потока

Разработаем простейшее многопоточное приложение, в котором каждый из потоков выводит на консоль свое сообщение.

using System;

using System.Threading;

class ThreadTest

{

static void Main()

{

Thread t = new Thread(WriteY);

t.Start();

while (true)

Console.Write("x");

}

static void WriteY()

{

while (true)

Console.Write("y");

}

}

Создадим метод WriteY, который выводит на экран букву «у». В методе Main, создадим поток связанный с методом WriteY, и запустим его при помощи метода Start. После этого в вечном цикле будем выводить на экран букву «x». Программа на C# запускается как единственный поток, автоматически создаваемый CLR и операционной системой (“главный” поток), и становится многопоточной при помощи создания дополнительных потоков.

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

static void Main()

{

new Thread(Go).Start();

Go();

Console.ReadLine();

}

static void Go()

{

for (int cycles = 0; cycles < 200; cycles++)

Console.WriteLine("cycles: {0}",cycles);

}

Отдельный экземпляр переменной cycles создается в стеке каждого потока, так что выводится свое собственное значение для каждого потока.

Управление многопоточностью осуществляет планировщик потоков, эту функцию CLR обычно делегирует операционной системе. Планировщик потоков гарантирует, что активным потокам выделяется соответствующее время на выполнение, а потоки, ожидающие или блокированные, не потребляют времени CPU.

На однопроцессорных компьютерах планировщик потоков использует квантование времени – быстрое переключение между выполнением каждого из активных потоков.

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

Типовое приложение с многопоточностью выполняет длительные вычисления в фоновом режиме. Главный поток продолжает выполнение, в то время как рабочий поток выполняет фоновую задачу. В приложениях Windows Forms, когда главный поток занят длительными вычислениями, он не может обрабатывать сообщения клавиатуры и мыши, и приложение перестает откликаться. По этой причине следует запускать отнимающие много времени задачи в рабочем потоке.

Другое применение многопоточность находит в методах, выполняющих интенсивные вычисления. Такие методы могут выполняться быстрее на многопроцессорных компьютерах, если рабочая нагрузка разнесена по нескольким потокам.

Многопоточность наряду с достоинствами имеет и свои недостатки. Самое главный из них – значительное увеличение сложности программ. Сложность увеличивают не дополнительные потоки сами по себе, а необходимость организации их взаимодействия. Кроме того, чрезмерное использование многопоточности отнимает ресурсы и время CPU на создание потоков и переключение между потоками.