18
Темы лекции: Асинхронное программирование в C#. Практическое задание: Асинхронное программирование в C#. Тренер: Игорь Шкулипа, к.т.н. Платформа .Net и язык программирования C#. Занятие 16

C# Desktop. Занятие 16

Embed Size (px)

Citation preview

Темы лекции: Асинхронное программирование в C#.

Практическое задание: Асинхронное программирование в C#.

Тренер: Игорь Шкулипа, к.т.н.

Платформа .Net и язык программирования C#.

Занятие 16

http://www.slideshare.net/IgorShkulipa 2

Асинхронное программирование

Асинхронное программирование — это набор методик дляреализации дорогостоящих операций, которые выполняютсяпараллельно с остальной частью программы. Одна из областей, гдечасто применяется асинхронное программирование, — программы сграфическим UI: как правило, замораживать UI до завершениядорогостоящей операции неприемлемо. Кроме того, асинхронныеоперации важны для серверных приложений, которым нужнопараллельно обрабатывать множество клиентских запросов.

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

http://www.slideshare.net/IgorShkulipa 3

Библиотека параллельных задач

Библиотека параллельных задач (TPL), как и предполагает ее имя, основываетсяна концепции задачи. Термин параллелизм задач означает одновременноевыполнение одной или нескольких разных задач. Задача представляет собойасинхронную операцию и в некотором роде напоминает создание нового потокаили рабочего элемента ThreadPool, но на более высоком уровне абстракции.

Задачи предоставляют два основных преимущества.

• Более эффективное и масштабируемое использование системных ресурсов.

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

• Больший программный контроль по сравнению с потоком или рабочимэлементом.

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

http://www.slideshare.net/IgorShkulipa 4

Тип Action<T>

public delegate void Action<in T>(T obj)

• T - тип параметра метода, инкапсулируемого данным делегатом.Этот параметр типа является контрвариантным. Это означает, чтоможно использовать либо указанный тип, либо менее производныйтип.

• obj - тип: T, Параметр метода, инкапсулируемого данным делегатом.

Делегат Action<T> можно использовать для передачи метода в качествепараметра без явного объявления пользовательского делегата.

Инкапсулируемый метод должен соответствовать заданной этимделегатом сигнатуре метода. Это означает, что инкапсулированный методдолжен иметь один параметр, передаваемый по значению, и не долженвозвращать значение.

http://www.slideshare.net/IgorShkulipa 5

Класс Task

using System.Threading.Tasks

[HostProtectionAttribute(SecurityAction.LinkDemand,

Synchronization = true,

ExternalThreading = true)]

public class Task : IAsyncResult, IDisposable

Представляет асинхронную операцию.

Task(Action) Инициализирует новую задачу Task с заданным действием.

Task(Action, CancellationToken)

Инициализирует новую задачу Task с заданными действием и токеном CancellationToken.

Task(Action, TaskCreationOptions)

Инициализирует новую задачу Task с заданными действием и параметрами создания.

Task(Action<Object>, Object)Инициализирует новую задачу Task с заданными действием и состоянием.

Task(Action, CancellationToken, TaskCreationOptions)

Инициализирует новую задачу Task с заданными действием и параметрами создания.

Task(Action<Object>, Object, CancellationToken)

Инициализирует новую задачу Task с заданными действием, состоянием и параметрами.

Task(Action<Object>, Object, TaskCreationOptions)

Инициализирует новую задачу Task с заданными действием, состоянием и параметрами.

Task(Action<Object>, Object, CancellationToken, TaskCreationOptions)

Инициализирует новую задачу Task с заданными действием, состоянием и параметрами.

http://www.slideshare.net/IgorShkulipa 6

Task. Свойства

AsyncStateВозвращает объект состояния, предоставленный при создании задачи Task, или значение NULL, если объект не предоставлен.

CreationOptionsВозвращает объект TaskCreationOptions, использованный при создании данной задачи.

CurrentIdВозвращает уникальный идентификатор выполняющейся в настоящее время задачи Task.

Exception

Возвращает объект AggregateException, который привел к преждевременному завершению задачи Task. Если Task завершенные успешно или пока не бросало исключений, это значение null.

FactoryПредоставляет доступ к методам фабрики для создания экземпляров Task и Task<TResult>.

IdВозвращает уникальный идентификатор данного экземпляра Task.

IsCanceledВозвращает значение, указывающее, завершилось ли выполнение данного экземпляра Task из-за отмены.

IsCompletedВозвращает значение, которое показывает, завершилась ли задача Task.

IsFaultedВозвращает значение, указывающее, завершилась ли задача Task из-за необработанного исключения.

Status Возвращает состояние TaskStatus данной задачи.

http://www.slideshare.net/IgorShkulipa 7

Task. Методы

http://msdn.microsoft.com/ru-ru/library/system.threading.tasks.task.aspx

http://www.slideshare.net/IgorShkulipa 8

Класс Parallel

Предоставляет поддержку параллельных циклов и областей.

[HostProtectionAttribute(SecurityAction.LinkDemand,

Synchronization = true,

ExternalThreading = true)]

public static class Parallel;

Методы:

• For + 10 перегрузок – выполняет цикл for с заданными аргументами• ForEach + 19 перегрузок – выполняет цикл foreach с заданными

аргументами• Invoke - выполняет все предоставленные действия, в том числе

параллельно.

http://www.slideshare.net/IgorShkulipa 9

Пример Task

Action<object> action = (object obj) =>

{

Console.WriteLine("Task={0}, Object={1}, Thread={2}",

Task.CurrentId, obj.ToString(),

Thread.CurrentThread.ManagedThreadId);

};

Task t1 = new Task(action, "StringObject1");

Task t2 = Task.Factory.StartNew(action, "StringObject2");

t2.Wait();

t1.Start();

t1.Wait();

Task t3 = new Task(action, "StringObject3");

t3.RunSynchronously();

t3.Wait();

Task=1, Object=StringObject2, Thread=11

Task=2, Object=StringObject1, Thread=11

Task=3, Object=StringObject3, Thread=10

http://www.slideshare.net/IgorShkulipa 10

Пример. Вычисление 10000 факториалов.Последовательная версия.

using System.Numerics;

class Program

{

static void Main(string[] args)

{

BigInteger FactorialsCount = 2000;

var Results = new Dictionary<BigInteger, BigInteger>();

Func<BigInteger, BigInteger> factorial = null;

factorial = (n) => (n == 0) ? 1 : n * factorial(n - 1);

for (BigInteger i = 0; i < FactorialsCount; i++)

{

Results.Add(i, factorial(i));

}

foreach (var item in Results)

{

Console.WriteLine("N={0}, Factorial={1}",

item.Key, item.Value);

}

Console.ReadKey();

}

}

http://www.slideshare.net/IgorShkulipa 11

Пример. Вычисление 10000 факториалов.Parallel версия.

using System.Numerics;

using System.Collections.Concurrent;

class Program

{

static void Main(string[] args)

{

int FactorialsCount = 10000;

var Results =

new ConcurrentDictionary<BigInteger, BigInteger>(4, FactorialsCount);

Func<int, BigInteger> factorial = null;

factorial = (n) =>

(n == 0) ? 1 : n * factorial(n - 1);

Parallel.For(0, FactorialsCount,

(i) =>

{

Results[i] = factorial(i);

});

foreach (var item in Results)

{

Console.WriteLine("N={0}, Factorial={1}",

item.Key, item.Value);

}

Console.ReadKey();

}

}

http://www.slideshare.net/IgorShkulipa 12

Пример. Вычисление 10000 факториалов.4-Parallel версия.

using System.Numerics;

using System.Collections.Concurrent;

class Program

{

static void Main(string[] args)

{

int FactorialsCount = 10000;

var Results =

new ConcurrentDictionary<BigInteger, BigInteger>(4, FactorialsCount);

Func<int, BigInteger> factorial = null;

factorial = (n) =>

(n == 0) ? 1 : n * factorial(n - 1);

for (int j = 0; j < 4; j++)

{

Parallel.For(j * 2500, (j + 1) * 2500,

(i) =>

{

Results[i] = factorial(i);

});

}

foreach (var item in Results)

{

Console.WriteLine("N={0}, Factorial={1}",

item.Key, item.Value);

}

Console.ReadKey();

}

}

http://www.slideshare.net/IgorShkulipa 13

Ключевое слово async

Модификатор async указывает, что модифицируемые им метод, лямбда-выражение, или анонимный метод являются асинхронными.

Асинронный метод может возвращать значение следующих типов: Task,Task<TResult> или void. Асинхронный метод не может принимать вкачестве своих аргументов параметры с модификаторами ref или out,но, при этом, он может вызывать методы, имеющие такие параметры.

Указывайте Task<TResult> в качестве типа значения, возвращаемогоасинхронным методом, в том случае, если оператор return этогометода возвращает операнд типа TResult. Если же асинхронный методпри своём завершении не возвращает имеющего смысл значения,используйте тип Task.

http://www.slideshare.net/IgorShkulipa 14

Оператор await

Оператор await применяется к задаче в асинхронных методах, для того,чтобы приостановить выполнение метода до тех пор, пока задача незавершится. Задача представляет собой выполняющихся работы.

Асинхронный метод, в котором используется await должен быть помеченмодификатором async. Такой метод, определенный с помощьюмодификатора async, и обычно содержащий один или нескольковыражений await, называется асинхронным методом.

http://www.slideshare.net/IgorShkulipa 15

Пример async и await

public class AsyncClassExample

{

public async Task<string> AsyncExample()

{

await Task.Delay(5000);

return "Async Method Finished";

}

}

class Program

{

static void Main(string[] args)

{

AsyncClassExample ace = new AsyncClassExample();

Task<string> t1 = ace.AsyncExample();

string result = t1.Result;

Console.WriteLine(result);

Console.ReadKey();

}

}Async Method Finished

http://www.slideshare.net/IgorShkulipa 16

Пример. Вычисление факториала 1000

public class AsyncFactorialClass {

public async Task<BigInteger> Factorial(BigInteger n) {

BigInteger result=0;

if (n == 0) return 1;

else

{

Task<BigInteger> t = Factorial(n - 1);

await t;

result = t.Result*n;

}

return result;

}

}

class Program {

static void Main(string[] args) {

AsyncFactorialClass ace = new AsyncFactorialClass();

Task<BigInteger> t1 = ace.Factorial(1000);

BigInteger result = t1.Result;

Console.WriteLine(result);

Console.ReadKey();

}

}

http://www.slideshare.net/IgorShkulipa 17

Факториал 1000

402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

http://www.slideshare.net/IgorShkulipa 18

Лабораторная работа №16. Асинхронное программирование в C#

В индивидуальных курсовых проектах при необходимости использоватьасинхронное программирование с помощью классов Task или Parallel, атак же асинхронные методы с модификатором async и операторомawait.