net framework и С#, весна 2015: Основы многопоточности. Часть 1

26
Толстиков Никита [email protected] Многопоточность 10.04.2015 1 Потоки

Upload: cs-center

Post on 18-Jul-2015

87 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Толстиков Никита

[email protected]

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

10.04.2015 1Потоки

Page 2: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

План лекции

• Введение в многопоточность

• Управление потоками

10.04.2015 Толстиков Никита 2Потоки

Page 3: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

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

• C# поддерживает параллельное

исполнение на уровне потоков:

10.04.2015 Толстиков Никита 3LINQ

public static void Example(){

Thread t = new Thread(WriteY); // Создаем новый потокt.Start(); // запускаем WriteY()// Паралельно делаем что-то на основном потоке.for (int i = 0; i < 1000; i++) Console.Write("x");

}static void WriteY(){

for (int i = 0; i < 1000; i++) Console.Write("y");}

//Получится что-то такое://xxxxyyyyyyxxyyyxyxyyxyxyxyyxyyyyyyyyyyyxxxxxxxxxxyyyyyyyyyyyxxxxxxxx...

Page 4: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

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

• Потоки выполняются последовательно на одном ядре и параллельно на нескольких

• Потоки выполняются по расписанию составленному ОС

• Минимальное время выполнения - квант

• Каждый поток имеет собственный стек и контекст, но остальная память общая

10.04.2015 Толстиков Никита 4Потоки

Page 5: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

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

10.04.2015 Толстиков Никита 5Потоки

class TestClass{

private bool isPrinted = false;

public void Print(){

if (!isPrinted){

Thread.Yield(); //Выйти из выполнения потокаisPrinted = true;Console.WriteLine("Printed");

}}

}

Page 6: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

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

• Каждый поток имеет ссылку на свой тестовый класс

• Вывод детерминирован

10.04.2015 Толстиков Никита 6Потоки

public static void ExampleOwn(){

var testClass1 = new TestClass();var testClass2 = new TestClass();Thread t = new Thread(testClass1.Print);t.Start();

testClass2.Print();

//Result://Printed//Printed

}

Page 7: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

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

• Оба потока имеют ссылку на один и тот

же класс

• Вывод не детерминирован

10.04.2015 Толстиков Никита 7Потоки

public static void ExampleShare(){

var testClass1 = new TestClass();Thread t = new Thread(testClass1.Print);t.Start();

testClass1.Print();

//Result://Printed//Printed (undefined behavior)

}

Page 8: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Создание и запуск

• Поток инкапсулирован в классе Thread из

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

• Для создания потока в него нужно

передать объект типа:

• Для запуска потока на исполнение нужно

вызвать метод Start

10.04.2015 Толстиков Никита 8Потоки

public delegate void ThreadStart();

Page 9: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Выполнение с аргументами

• Первый способ:

10.04.2015 Толстиков Никита 9Потоки

static void Example(){

Thread t = new Thread(() => Print("Hello from t!"));t.Start();

}

static void Print(string message){

Console.WriteLine(message);}

Page 10: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Выполнение с аргументами

• Примечание:

– Контекст может меняться:

10.04.2015 Толстиков Никита 10Потоки

string text = "text1";Thread t1 = new Thread(() => Console.WriteLine(text));

text = "text2";Thread t2 = new Thread(() => Console.WriteLine(text));

t1.Start();t2.Start();

//Result://text2//text2

Page 11: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Выполнение с аргументами

• Примечание:

– Контекст может меняться:

– FIX:

10.04.2015 Толстиков Никита 11Потоки

for (int i = 0; i < 10; i++){

new Thread(() => Console.Write(i)).Start();}//Result://0223557799

for (int i = 0; i < 10; i++){

int i1 = i;new Thread(() => Console.Write(i1)).Start();

}//Result://0123456789

Page 12: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Выполнение с аргументами

• Второй способ:

– Конструктор принимает также объект типа

10.04.2015 Толстиков Никита 12Потоки

static void Example(){

Thread t = new Thread(Print);t.Start("Hello from t!");

}

static void Print(object message){

string stringMessage = (string) message; //Нужен кастConsole.WriteLine(stringMessage);

}

public delegate void ParameterizedThreadStart(object obj);

Page 13: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Join

• Метод Join – дожидается окончания

выполнения потока

• Во время исполнения Join поток

находится в заблокированном состоянии и

не потребляет системных ресурсов

10.04.2015 Толстиков Никита 13Потоки

public void Join() ...public bool Join(int millisecondsTimeout)...public bool Join(TimeSpan timeout)...

Page 14: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Sleep

• Метод Sleep – ставит выполнения потока на паузу

• Метод Thread.Yield – аналогичен Thread.Sleep(0)

• Метод Thread.Yield можно поставить в любое место программы и она не должна сломаться

10.04.2015 Толстиков Никита 14Потоки

public bool Sleep(int millisecondsTimeout)...public bool Sleep(TimeSpan timeout)...

Page 15: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Именованные потоки

• Потоки имеют свойство Name

• Оно крайне полезно при отладке в

VisualStudio

10.04.2015 Толстиков Никита 15Потоки

public static void Example(){

Thread.CurrentThread.Name = "main";Thread worker = new Thread(Go);worker.Name = "worker";worker.Start();Go();

}static void Go(){

Console.WriteLine("Hello from " + Thread.CurrentThread.Name);}

Page 16: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Foreground и Background потоки

• Программа исполняется пока исполняется

хоть один foregraund поток

• По умолчанию все потоки foregraund

• Для изменения типа потока используется

свойство IsBackground

10.04.2015 Толстиков Никита 16Потоки

Page 17: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Foreground и Background потоки

• Если количество аргументов больше нуля, то программа не будет ждать ввода клавиши и сразу завершиться

• При завершении в таком стиле finally блоки в background потоках не выполняться

– Использовать Join

– Использовать пул-потоков

10.04.2015 Толстиков Никита 17Потоки

static void Main(string[] args){

Thread worker = new Thread(() => Console.ReadLine());if (args.Length > 0) worker.IsBackground = true;worker.Start();

}

Page 18: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Обработка исключений

• Любые try/catch/finally блоки

нерелевантны точке старта потока:

10.04.2015 Толстиков Никита 18Потоки

public static void Example(){

try{

new Thread(Go).Start();}catch (Exception ex){

// We'll never get here!Console.WriteLine("Exception!");

}}

static void Go() { throw null; }

Page 19: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Обработка исключений

• Контроль исключений должен

осуществляться в корневом методе потока:

10.04.2015 Толстиков Никита 19Потоки

public static void Example(){

new Thread(Go).Start();}static void Go(){

try{

throw null; // NullReferenceException будет поймано ниже}catch (Exception ex){

// Что-то залогировать, или посигналить другому потоку и закончить //исполнение

}}

Page 20: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Пул потоков

• Создает потоки заранее

• Позволяет пере использовать потоки

• Уменьшает оверхед при частом создании потоков

• По умолчанию потоки являются background

• Удобно использовать для «быстрых задач» в несколько квантов

• Для долгих (порядка секунд) лучше создавать потоки вручную

10.04.2015 Толстиков Никита 20Потоки

Page 21: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

Пул потоков

10.04.2015 Толстиков Никита 21Потоки

public static void Example(){

ThreadPool.QueueUserWorkItem(Go);ThreadPool.QueueUserWorkItem(Go, 123);Console.ReadLine();

}

static void Go(object data) // data will be null with the //first call.

{Console.WriteLine("Hello from the thread pool! " + data);

}

//Results://Hello from the thread pool!//Hello from the thread pool! 123

Page 22: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

• Как обычные, но вызываются асинхронно

на потоках из пула

Асинхронные делегаты

10.04.2015 Толстиков Никита 22Потоки

public static void Example(){

Func<string, int> method = Work;IAsyncResult cookie = method.BeginInvoke("test", null, null);//// ... here's where we can do other work in parallel...//int result = method.EndInvoke(cookie);Console.WriteLine("String length is: " + result);

}

static int Work(string s) { return s.Length; }

Page 23: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

• BeginInvoke запускает метод на исполнение и возвращает IAsincResult«талончик» на получение результата

Асинхронные делегаты

10.04.2015 Толстиков Никита 23Потоки

public static void Example(){

Func<string, int> method = Work;IAsyncResult cookie = method.BeginInvoke("test", null, null);//// ... here's where we can do other work in parallel...//int result = method.EndInvoke(cookie);Console.WriteLine("String length is: " + result);

}

static int Work(string s) { return s.Length; }

Page 24: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

• EndInvoke дожидается исполнения метода по «талончику» и возвращает результат

• Так же перебрасывает необработанные исключения

Асинхронные делегаты

10.04.2015 Толстиков Никита 24Потоки

public static void Example(){

Func<string, int> method = Work;IAsyncResult cookie = method.BeginInvoke("test", null, null);//// ... here's where we can do other work in parallel...//int result = method.EndInvoke(cookie);Console.WriteLine("String length is: " + result);

}

static int Work(string s) { return s.Length; }

Page 25: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

• В BeginInvoke можно передать callback, который вызовется при завершении метода и объект как параметр

Асинхронные делегаты

10.04.2015 Толстиков Никита 25Потоки

public static void Example(){

Func<string, int> method = Work;method.BeginInvoke("test", Done, method);// ...//

}

static int Work(string s) { return s.Length; }

static void Done(IAsyncResult cookie){

var target = (Func<string, int>)cookie.AsyncState;int result = target.EndInvoke(cookie);Console.WriteLine("String length is: " + result);

}

Page 26: Net Framework и С#, весна 2015: Основы многопоточности. Часть 1

The End

10.04.2015 Толстиков Никита 26LINQ