class Thread Unsafe static int val 1 1

  • Slides: 38
Download presentation

Блокирующие конструкции class Thread. Unsafe { static int _val 1 = 1, _val 2

Блокирующие конструкции class Thread. Unsafe { static int _val 1 = 1, _val 2 = 1; static void Go() { if (_val 2 != 0) Console. Write. Line(_val 1 / _val 2); _val 2 = 0; } } 30. 09. 2020 Толстиков Никита Потоки 7

Блокирующие конструкции class Thread. Safe { static readonly object _locker = new object(); static

Блокирующие конструкции class Thread. Safe { static readonly object _locker = new object(); static int _val 1, _val 2; static void Go() { lock (_locker) { if (_val 2 != 0) Console. Write. Line(_val 1 / _val 2); _val 2 = 0; } } } 30. 09. 2020 Толстиков Никита Потоки 8

Блокирующие конструкции Конструкция lock (Monitor. Enter и Monitor. Exit) Mutex Cross-process? - Overhead 20

Блокирующие конструкции Конструкция lock (Monitor. Enter и Monitor. Exit) Mutex Cross-process? - Overhead 20 ns Yes 1000 ns Semaphore. Slim (введен в Framework 4. 0) 200 ns Semaphore Yes 1000 ns Reader. Writer. Lock. Slim (введен в Framework 3. 5) - 40 ns Reader. Writer. Lock (устарел) - 100 ns 30. 09. 2020 Толстиков Никита Потоки 10

Deadlocks • Происходят когда два потока, каждый из которых ждет ресурса, удерживаемого другим object

Deadlocks • Происходят когда два потока, каждый из которых ждет ресурса, удерживаемого другим object locker 1 = new object(); object locker 2 = new object(); new Thread(() => { lock (locker 1) { Thread. Sleep(1000); lock (locker 2) ; // Deadlock } }). Start(); lock (locker 2) { Thread. Sleep(1000); lock (locker 1) ; // Deadlock } 30. 09. 2020 Толстиков Никита Потоки 13

Deadlocks • Происходят когда два потока, каждый из которых ждет ресурса, удерживаемого другим object

Deadlocks • Происходят когда два потока, каждый из которых ждет ресурса, удерживаемого другим object locker 1 = new object(); object locker 2 = new object(); new Thread(() => { lock (locker 1) { Thread. Sleep(1000); lock (locker 2) ; // Deadlock } }). Start(); lock (locker 2) { Thread. Sleep(1000); lock (locker 1) ; // Deadlock } 30. 09. 2020 Толстиков Никита Потоки 14

Semaphores class The. Club // No door lists! { static Semaphore. Slim _sem =

Semaphores class The. Club // No door lists! { static Semaphore. Slim _sem = new Semaphore. Slim(3); // Capacity of 3 static void Main() { for (int i = 1; i <= 5; i++) new Thread(Enter). Start(i); } static void Enter(object id) { Console. Write. Line(id + " wants to enter"); _sem. Wait(); Console. Write. Line(id + " is in!"); Thread. Sleep(1000 * (int)id); Console. Write. Line(id + " is leaving"); _sem. Release(); } // Only three threads // can be here at // a time. } //1 //2 //3 //4 wants to is in! wants to 30. 09. 2020 enter //5 //1 //4 //2 //5 wants to enter is leaving is in! enter Толстиков Никита Потоки 16

Parallel class for (int i = 0; i < 100; i++) Foo (i); •

Parallel class for (int i = 0; i < 100; i++) Foo (i); • Паралелится как: Parallel. For (0, 100, i => Foo (i)); Parallel. For (0, 100, Foo); foreach (char c in "Hello, world") Foo (c); • Паралелится как: Parallel. For. Each ("Hello, world", Foo); 30. 09. 2020 Толстиков Никита Потоки 23

Создание и запуск задач • Chlid. Task – родитель ждет исполнения всех Child. Task:

Создание и запуск задач • Chlid. Task – родитель ждет исполнения всех Child. Task: Task parent = Task. Factory. Start. New(() => { Console. Write. Line("I am a parent"); Task. Factory. Start. New(() => // Detached task { Console. Write. Line("I am detached"); }); Task. Factory. Start. New(() => // Child task { Console. Write. Line("I am a child"); }, Task. Creation. Options. Attached. To. Parent); }); 30. 09. 2020 Толстиков Никита Потоки 28

Ожидание задач • Ожидание завершения задачи можно двумя способами: – Wait, Wait. All или

Ожидание задач • Ожидание завершения задачи можно двумя способами: – Wait, Wait. All или Wait. Any: var exceptions = new List<Exception>(); Task t 1 = Task. Factory. Start. New(Work); Task t 2 = Task. Factory. Start. New(Work); Task t 3 = Task. Factory. Start. New(Work); Task[] tasks = new []{t 1, t 2, t 3} try { t 1. Wait(); }. . . catch (Aggregate. Exception ex) { exceptions. Add(ex); } Task. Wait. All(tasks); Task. Wait. Any(tasks); if (exceptions. Count > 0) throw new Aggregate. Exception(exceptions); – Вызвать Result, если у задачи есть возвращаемое значение 30. 09. 2020 Толстиков Никита Потоки 29

Обработка исключений • Необработанные исключения выбрасываются в момент ожидания задачи • Оборачиваются в Aggregate.

Обработка исключений • Необработанные исключения выбрасываются в момент ожидания задачи • Оборачиваются в Aggregate. Exception int x = 0; Task<int> calc = Task. Factory. Start. New(() => 7 / x); try { Console. Write. Line(calc. Result); } catch (Aggregate. Exception aex) { Console. Write(aex. Inner. Exception. Message); // Attempted to divide by 0 } 30. 09. 2020 Толстиков Никита Потоки 30

Обработка исключений • Необработанные исключения выбрасываются в момент ожидания задачи • Оборачиваются в Aggregate.

Обработка исключений • Необработанные исключения выбрасываются в момент ожидания задачи • Оборачиваются в Aggregate. Exception int x = 0; Task<int> calc = Task. Factory. Start. New(() => 7 / x); try { Console. Write. Line(calc. Result); } catch (Aggregate. Exception aex) { Console. Write(aex. Inner. Exception. Message); // Attempted to divide by 0 } 30. 09. 2020 Толстиков Никита Потоки 31

Остановка задачи var cancel. Source = new Cancellation. Token. Source(); Cancellation. Token token =

Остановка задачи var cancel. Source = new Cancellation. Token. Source(); Cancellation. Token token = cancel. Source. Token; Task task = Task. Factory. Start. New (() => { // Do some stuff. . . token. Throw. If. Cancellation. Requested(); // Check for cancellation request // Do some stuff. . . }, token); . . . cancel. Source. Cancel(); . . . try { task. Wait(); } catch (Aggregate. Exception ex) { if (ex. Inner. Exception is Operation. Canceled. Exception) Console. Write ("Task canceled!"); } 30. 09. 2020 Толстиков Никита Потоки 33

Piplines • Задачи можно объединять в pipline’ы используя метод Continue. With у Task task

Piplines • Задачи можно объединять в pipline’ы используя метод Continue. With у Task task 1 = Task. Factory. Start. New(() => { throw null; }); Task error = task 1. Continue. With(ant =>Console. Write(ant. Exception), Task. Continuation. Options. Only. On. Faulted); Task ok = task 1. Continue. With(ant => Console. Write("Success!"), Task. Continuation. Options. Not. On. Faulted); 30. 09. 2020 Толстиков Никита Потоки 34

Piplines • Или используя различные методы Continue* у Task. Factory var task 1 =

Piplines • Или используя различные методы Continue* у Task. Factory var task 1 = Task. Factory. Start. New(() => Console. Write("X")); var task 2 = Task. Factory. Start. New(() => Console. Write("Y")); var continuation = Task. Factory. Continue. When. All( new[] { task 1, task 2 }, tasks => Console. Write. Line("Done")); 30. 09. 2020 Толстиков Никита Потоки 35

The End 30. 09. 2020 Толстиков Никита LINQ 38

The End 30. 09. 2020 Толстиков Никита LINQ 38