SlideShare a Scribd company logo
1 of 120
Download to read offline
Wild Async
.NET world
By Vladimir Garbar
.NET Meetup
Play
hys-enterprise.com
My experience
.NET Developer
Team Lead @ HYS Enterprise
.NET Meetup
HYS Enterprise is a Dutch software
development company with more than
200 talented engineers from all over
the world hys-enterprise.com
UkraineNetherlands
Wild Async .NET world
AID Kit for boy scouts
.NET Meetup
План
1. Общие понятия
2. Async + Await
3. Практики
.NET Meetup
Общие понятия
.NET Meetup
Конкурентность
Выполнение нескольких действий в одно и то же время
.NET Meetup
Конкурентность
Полезность:
- В любой ситуации, когда приложение должно делать что-то одно во
время работы над чем-то другим.
- Для конечного пользователя, чтобы реагировать на ввод данных
пользователем во время записи в базу данных.
- Серверные приложения используют конкурентность для реакции на
второй запрос в ходе завершения первого запроса.
.NET Meetup
Многопоточность
Форма конкурентности, использующая несколько
потоков выполнения
.NET Meetup
Параллельная обработка
Выполнение большого объема работы за счет
распределения ее между несколькими потоками,
выполняемыми одновременно
.NET Meetup
Асинхронное программирование
Разновидность конкурентности, использующая
обещания или обратные вызовы для предотвращения
создания лишних потоков
.NET Meetup
Преимущества
.NET Meetup
Преимущества
● Уменьшает сложность
● Улучшает читаемость
.NET Meetup
Преимущества
● Производительность?
.NET Meetup
Преимущества
● Производительность?
.NET Meetup
Преимущества
● Производительность?
● Масштабируемость!
.NET Meetup
Масштабируемость
● Горизонтальная
● Вертикальная
.NET Meetup
Горизонтальная масштабируемость
Добавление количества серверов:
- RESTful
- Распределенные базы данных
- Кэширование данных
- Отсутствие сессии
.NET Meetup
Вертикальная масштабируемость
Улучшение качеств текущих серверов:
- Больше RAM
- Быстрые HDD
- Больше CPU Cores
- Более оптимальное использование ресурсов
- Оптимальное использование потоков
- Освобождение потока как можно скорее
.NET Meetup
Параллельная обработка
Использует потоки, которые иначе бы простаивали
.NET Meetup
Асинхронное программирование
Освобождает потоки
.NET Meetup
Подводные камни
● Проблемы с общим доступом
● Восстановление контекста
● Deadlock
● Сложно использовать
.NET Meetup
Async + Await
.NET Meetup
Async
● Добавляется в объявление метода.
● Разрешает использование ключевого слова await внутри этого метода.
● Дает инструкцию компилятору сгенерировать для этого метода
конечный автомат
.NET Meetup
Await
● Выполняет асинхронное ожидание по своему аргументу. Сначала
проверяет, завершилась ли операция: если да, то метод продолжает
выполняться синхронно.
● В противном случае await приостанавливает async-метод и возвращает
незавершенную задачу.
● Когда операция завершится позднее, метод async продолжает
выполнение.
.NET Meetup
Async-метод
Может рассматриваться как состоящий из нескольких синхронных частей,
разделенных командами await.
.NET Meetup
Async-метод
Первая синхронная часть выполняется в потоке, который вызвал метод.
Все синхронные части пытаются возобновить продолжение в исходном
контексте.
Если вызвать метод DoSomethingAsync из UI-потока, каждая из его
синхронных частей будет выполняться в этом UI-потоке, но если вызвать
его из потока из пула потоков, то каждая из синхронных частей будет
выполняться в любом потоке из пула потоков.
.NET Meetup
Синхронизация контекста
● UI thread
● ASP.NET
.NET Meetup
Взаимоблокировка
.NET Meetup
void Deadlock()
{
Task task = WaitAsync();
// Синхронное блокирование с
ожиданием завершения async метода.
task.Wait();
}
async Task WaitAsync()
{
// await сохранит текущий контекст
await Task.Delay(TimeSpan.FromSeconds(1));
// попытается возобновить метод в этой точке с
этим контекстом.
}
Синхронизация контекста
● ConfigureAwait(false)
● await
.NET Meetup
Взаимоблокировка: Решение
.NET Meetup
void Deadlock()
{
Task task = WaitAsync();
// Синхронное блокирование с
ожиданием завершения async метода.
task.Wait();
}
async Task WaitAsync()
{
await Task.Delay(TimeSpan.FromSeconds(1))
.ConfigureAwait(false);
}
Взаимоблокировка: Лучшее
.NET Meetup
async void Deadlock()
{
Task task = await WaitAsync();
}
async Task WaitAsync()
{
// await сохранит текущий контекст
await Task.Delay(TimeSpan.FromSeconds(1));
// попытается возобновить метод в этой точке с
этим контекстом.
}
Синхронизация контекста
Хорошей практикой считается вызывать ConfigureAwait в базовых
“библиотечных” методах и возобновлять контекст только тогда, когда
потребуется - в ваших внешних методах “пользовательского интерфейса”.
.NET Meetup
Синхронизация контекста
ConfigureAwait(false) конфигурирует Task так, что возвращение из await не
обязательно должно выполняться в вызывающем контексте.
Использовалось для избегания Deadlocks.
И для того, чтобы не ожидать вызывающий контекст.
.NET Meetup
Синхронизация контекста
ASP.NET Core не имеет синхронизации контекста
- Используется Thread pool
- Улучшает производительность
- Легче писать async code. Не ответственность разработчика
- Task.Result больше не приводит к Deadlock,
но приводит к блокировке вызывающего потока
.NET Meetup
Синхронизация контекста
ConfigureAwait(false) больше не требуется для .NET Core
Но желательно для .NET Standard 2.0, который может работать под .NET
Framework
.NET Meetup
Практики
.NET Meetup
Синхронный код + асинхронный
.NET Meetup
Синхронный код + асинхронный
.NET Meetup
async Task<string> DownloadStringAsync(HttpClient client, string uri)
{
return await client.GetStringAsync(uri);
}
Синхронный код + асинхронный
.NET Meetup
string DownloadString(HttpClient client, string uri)
{
return await client.GetStringAsync(uri); // Error!
}
Синхронный код + асинхронный
.NET Meetup
string DownloadString(HttpClient client, string uri)
{
return client.GetStringAsync(uri).Result;
}
Синхронный код + асинхронный
.NET Meetup
string DownloadString(HttpClient client, string uri)
{
return client.GetStringAsync(uri).GetAwaiter().GetResult();
}
Синхронный код + асинхронный
.NET Meetup
async Task<string> DownloadStringAsync(HttpClient client, string uri)
{
return await client.GetStringAsync(uri);
}
Синхронный код + асинхронный
.NET Meetup
async Task<string> DownloadStringAsync(HttpClient client, string uri)
{
return await client.GetStringAsync(uri);
}
Синхронный код + асинхронный
.NET Meetup
Task<string> DownloadStringAsync(HttpClient client, string uri)
{
return client.GetStringAsync(uri);
}
Синхронный код + асинхронный
.NET Meetup
async Task<string> DownloadStringAsync(HttpClient client, string uri)
{
return await client.GetStringAsync(uri);
}
Синхронный код + асинхронный
.NET Meetup
async Task<string> DownloadStringAsync(HttpClient client, string uri)
{
try
{
return await client.GetStringAsync(uri);
}
catch(Exception)
{
// обработаем ошибку
}
}
Синхронный код + асинхронный
.NET Meetup
Task<string> DownloadStringAsync(HttpClient client, string uri)
{
try
{
return client.GetStringAsync(uri);
}
catch(Exception)
{
// сюда не попадем :(
}
}
Синхронный код + асинхронный
.NET Meetup
async Task<string> DownloadStringAsync(HttpClient client, string uri)
{
try
{
return await client.GetStringAsync(uri);
}
catch(Exception)
{
// обработаем ошибку
}
}
Синхронный код + асинхронный
.NET Meetup
Task<string> DownloadStringAsync(HttpClient client, string uri)
{
return client.GetStringAsync(uri);
}
Синхронный код + асинхронный
.NET Meetup
Task DoSomethingAsync()
{
return Task.CompletedTask;
}
Синхронный код + асинхронный
.NET Meetup
Task<int> GetValueAsync()
{
return Task.FromResult(200);
}
Синхронный код + асинхронный
.NET Meetup
Task<int> GetValueAsync(CancellationToken cancellationToken)
{
if (cancellationToken.IsCancellationRequested)
return Task.FromCanceled<int>(cancellationToken);
return Task.FromResult(200);
}
Синхронный код + асинхронный
.NET Meetup
Task<T> ExceptionAsync<T>()
{
return Task.FromException<T>(new NotImplementedException());
}
Синхронный код + асинхронный
.NET Meetup
Task DoSomethingAsync()
{
try
{
DoSomething();
return Task.CompletedTask;
}
catch (Exception ex)
{
return Task.FromException(ex);
}
}
Async
Async метод возвращает:
● void
● Task, Task<TResult>
● ValueTask, ValueTask<T>
● IAsyncEnumerable<T>, IAsyncEnumerator<T>
.NET Meetup
async void
● Только для event handlers
● Тяжело обрабатывать ошибки
● Сложно тестировать
● Нелегко оповещать вызывающий код о статусе своего выполнения
.NET Meetup
ValueTask
● Cокращает затраты памяти, если результат в основном является
синхронным.
● Например, если результат может быть прочитан из кэша в памяти.
.NET Meetup
ValueTask
.NET Meetup
async ValueTask<int> GetOrderAsync()
{
if (_cachedOrder != 0)
return _cachedOrder;
_cachedOrder = await GetOrderFromStorageAsync();
return _cachedOrder;
}
ValueTask: недостатки
● ValueTask или ValueTask<T> может ожидаться только один раз
● Можно вызвать AsTask только один раз.
● Синхронная загрузка результата из Task<T> блокирует вызывающий
поток до завершения задачи; ValueTask<T> таких гарантий не дает.
● Синхронное получение результатов от ValueTask или ValueTask<T>
● может быть выполнено только один раз, после завершения ValueTask.
.NET Meetup
IAsyncEnumerable<T>
Работает так же, как и IEnumerable<T>, только асинхронно получает каждый
следующий элемент.
.NET Meetup
IAsyncEnumerable<T>
.NET Meetup
async IAsyncEnumerable<int> GetValuesAsync()
{
await Task.Delay(1000); // сложные расчеты или загрузка из сети
yield return 1;
await Task.Delay(1000); // сложные расчеты или загрузка из сети
yield return 2;
}
IAsyncEnumerable<T>
.NET Meetup
IAsyncEnumerable<string> GetValuesAsync(HttpClient client);
async Task ProcessValueAsync(HttpClient client)
{
await foreach (string value in GetValuesAsync(client))
{
Console.WriteLine(value);
}
}
IAsyncEnumerable<T>
.NET Meetup
IAsyncEnumerable<string> GetValuesAsync(HttpClient client);
async Task ProcessValueAsync(HttpClient client)
{
await foreach (string value in GetValuesAsync(client))
{
await Task.Delay(100); // асинхронно обрабатываем элемент
Console.WriteLine(value);
}
}
IAsyncEnumerable<T>
.NET Meetup
IAsyncEnumerable<string> GetValuesAsync(HttpClient client);
async Task ProcessValueAsync(HttpClient client)
{
await foreach (string value in GetValuesAsync(client).ConfigureAwait(false)))
{
await Task.Delay(100).ConfigureAwait(false)); // асинхронно обрабатываем элемент
Console.WriteLine(value);
}
}
.NET Meetup
async IAsyncEnumerable<string> GetValuesAsync(HttpClient client)
{
int offset = 0;
const int limit = 10;
while (true)
{
var result = await client.GetStringAsync($"https://my.com/api/values?offset={offset}&limit={limit}");
string[] items = result.Split('n');
foreach (string item in items)
yield return item;
if (items.Length < limit)
break; // елементов меньше - последняя страница
offset += limit;
}
}
Ожидание нескольких задач
.NET Meetup
Ожидание нескольких задач
.NET Meetup
Task task1 = Task.Delay(TimeSpan.FromSeconds(3));
Task task2 = Task.Delay(TimeSpan.FromSeconds(2));
Task task3 = Task.Delay(TimeSpan.FromSeconds(1));
await Task.WhenAll(task1, task2, task3);
Ожидание нескольких задач
.NET Meetup
Task<int> task1 = Task.FromResult(3);
Task<int> task2 = Task.FromResult(2);
Task<int> task3 = Task.FromResult(1);
int[] results = await Task.WhenAll(task1, task2, task3);
.NET Meetup
async Task ProcessTasksAsync()
{
Task<string> taskA = DelayAndReturnAsync(3, "medium");
Task<string> taskB = DelayAndReturnAsync(5, "slow");
Task<string> taskC = DelayAndReturnAsync(1, "fast");
Task<string>[] tasks = new[] { taskA, taskB, taskC };
foreach (var task in tasks)
{
var result = await task;
Results.Add(result);
}
}
async Task<string> DelayAndReturnAsync(int delay, string value)
{
await Task.Delay(TimeSpan.FromSeconds(delay));
return value;
}
.NET Meetup
async Task ProcessTasksAsync()
{
Task<string> taskA = DelayAndReturnAsync(3, "medium");
Task<string> taskB = DelayAndReturnAsync(5, "slow");
Task<string> taskC = DelayAndReturnAsync(1, "fast");
Task<string>[] tasks = new[] { taskA, taskB, taskC };
foreach (var task in tasks)
{
var result = await task;
Results.Add(result);
}
}
async Task<string> DelayAndReturnAsync(int delay, string value)
{
await Task.Delay(TimeSpan.FromSeconds(delay));
return value;
}
"medium"
"slow"
"fast"
.NET Meetup
async Task ProcessTasksAsync()
{
Task<string> taskA = DelayAndReturnAsync(3, "medium");
Task<string> taskB = DelayAndReturnAsync(5, "slow");
Task<string> taskC = DelayAndReturnAsync(1, "fast");
Task<string>[] tasks = new[] { taskA, taskB, taskC };
Task<string>[] processingTasks = tasks.Select(async t =>
{
var result = await t;
Result.Add(result);
return result;
}).ToArray();
await Task.WhenAll(processingTasks);
}
"fast"
"medium"
"slow"
Синхронизация
.NET Meetup
Синхронизация
Если в вашем приложении используется конкурентность,
следует остерегаться ситуаций, в которых один блок
кода должен обновлять данные, пока другой код
обращается к тем же данным. Столкнувшись с подобной
ситуацией, необходимо синхронизировать доступ к
данным
.NET Meetup
Синхронизация
Основные виды синхронизации:
● передачи данных
● защиты данных
.NET Meetup
Синхронизация для защиты
Необходима при выполнении всех трех условий:
1. Несколько частей кода выполняются одновременно
2. Общие данные
3. Обновление данных
.NET Meetup
Синхронизация для защиты
Цель защиты данных заключается в том, чтобы каждая
часть кода имела целостное представление данных.
Если одна часть кода обновляет данные, вы можете
воспользоваться синхронизацией, чтобы обновления
воспринимались как атомарные для остальных
компонентов системы.
.NET Meetup
Нужна синхронизации для value?
.NET Meetup
async Task<int> MyMethodAsync()
{
int value = 10;
await Task.Delay(TimeSpan.FromSeconds(1));
value += 1;
await Task.Delay(TimeSpan.FromSeconds(1));
value += 1;
await Task.Delay(TimeSpan.FromSeconds(1));
return await Task.FromResult(value);
}
Нужна синхронизации для value?
.NET Meetup
async Task<int> MyMethodAsync()
{
int value = 10;
await Task.Delay(TimeSpan.FromSeconds(1));
value += 1;
await Task.Delay(TimeSpan.FromSeconds(1));
value += 1;
await Task.Delay(TimeSpan.FromSeconds(1));
return await Task.FromResult(value);
}
Нет
Нужна синхронизации для value?
.NET Meetup
private int value;
async Task ModifyValueAsync()
{
var originalValue = value;
await Task.Delay(TimeSpan.FromSeconds(1));
value = originalValue + 1;
}
Нужна синхронизации для value?
.NET Meetup
private int value;
async Task ModifyValueAsync()
{
var originalValue = value;
await Task.Delay(TimeSpan.FromSeconds(1));
value = originalValue + 1;
}
Да
Lock блокировка
.NET Meetup
private readonly object _mutex = new object();
private int _value;
public void Increment()
{
lock (_mutex)
{
_value = _value + 1;
}
}
Lock блокировка
.NET Meetup
● Ограничьте видимость блокировки:
private объект, не string, не this
● Защищать только то, что должно быть защищено
● Минимальный объем кода, защищенного блокировкой:
минимум блокирующих вызовов в lock
● Никакого произвольного кода при удержании блокировки:
не инициируйте события, не вызывайте делегаты и другие методы
Async блокировка
.NET Meetup
.NET Meetup
private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1);
private int _value;
public async Task DelayAndIncrementAsync()
{
await _mutex.WaitAsync();
try
{
int oldValue = _value;
await Task.Delay(TimeSpan.FromSeconds(oldValue));
_value = oldValue + 1;
}
finally
{
_mutex.Release();
}
}
Синхронизация передачи данных
Синхронизация при передаче данных используется в тех
случаях, когда один блок кода должен оповестить другой
блок кода о некотором условии (например, о
поступлении нового сообщения)
.NET Meetup
Блокировка через сигналы
.NET Meetup
private readonly ManualResetEventSlim _initialized = new ManualResetEventSlim();
private int _value;
public int ReturnResultFromThreadA()
{
_initialized.Wait();
return _value;
}
public void InitializeFromThreadB()
{
_value = 13;
_initialized.Set();
}
Async блокировка через сигналы
.NET Meetup
private readonly TaskCompletionSource<object> _initialized = new TaskCompletionSource<object>();
private int _value;
public async Task<int> WaitForInitializationAsync()
{
await _initialized.Task;
return _value1 + 1;
}
public void Initialize()
{
_value = 5;
_initialized.TrySetResult(null);
}
Исключения
.NET Meetup
Исключения
.NET Meetup
async Task TestAsync()
{
try
{
await ThrowExceptionAsync();
}
catch (InvalidOperationException)
{
}
}
async Task ThrowExceptionAsync()
{
await
Task.Delay(TimeSpan.FromSeconds(5));
throw new InvalidOperationException("Error");
}
.NET Meetup
async Task ObserveOneExceptionAsync()
{
var task1 = ThrowNotImplementedExceptionAsync();
var task2 = ThrowInvalidOperationExceptionAsync();
try
{
await Task.WhenAll(task1, task2);
}
catch (Exception ex)
{
// Какие exception будут здесь?
}
}
async Task ThrowNotImplementedExceptionAsync()
{
throw new NotImplementedException();
}
async Task ThrowInvalidOperationExceptionAsync()
{
throw new InvalidOperationException();
}
.NET Meetup
async Task ObserveOneExceptionAsync()
{
var task1 = ThrowNotImplementedExceptionAsync();
var task2 = ThrowInvalidOperationExceptionAsync();
Task allTasks = Task.WhenAll(task1, task2);
try
{
await allTasks;
}
catch (Exception ex)
{
AggregateException allExceptions =
allTasks.Exception;
}
}
async Task ThrowNotImplementedExceptionAsync()
{
throw new NotImplementedException();
}
async Task ThrowInvalidOperationExceptionAsync()
{
throw new InvalidOperationException();
}
async Task<MultipartFormDataStreamProvider> Read(HttpContent content)
{
var multipartContentProvider = new MultipartFormDataStreamProvider(_tmpFolderPath);
var task = content.ReadAsMultipartAsync(multipartContentProvider);
if (task.IsFaulted || task.IsCanceled)
throw new ContentFormatException($"HTTP message is not in correct format");
return await task;
}
Исключения: Bad Code
.NET Meetup
.NET Meetup
async Task TestAsync()
{
Task task = ThrowExceptionAsync(); // Исключение выдается методом и помещается в задачу
try
{
await task; // Здесь исключение будет выдано повторно
}
catch (Exception)
{
// Здесь исключение правильно перехватывается.
}
}
Исключения: Good Code
Задержка
.NET Meetup
Задержка
Когда может понадобиться:
● В надежде, что другая операция закончилась
● Тестирование
● Повтор операции через время
.NET Meetup
.NET Meetup
Задержка
async Task<T> DelayResult<T>(T result, TimeSpan delay)
{
Thread.Sleep(delay);
return await Task.FromResult(result);
}
.NET Meetup
Задержка
async Task<T> DelayResult<T>(T result, TimeSpan delay)
{
Thread.Sleep(delay);
return await Task.FromResult(result);
}
async Task<T> DelayResult<T>(T result, TimeSpan delay)
{
await Task.Delay(delay);
return result;
}
Задержка
Повтор операции
● Без задержки
● С постоянной задержкой
● С увеличивающейся задержкой
.NET Meetup
.NET Meetup
async Task<string> DownloadStringWithRetries(HttpClient client, string uri)
{
for (int i = 0; i < 4; i++)
{
try
{
return await client.GetStringAsync(uri);
}
catch
{
}
}
return await client.GetStringAsync(uri);
}
.NET Meetup
async Task<string> DownloadStringWithRetries(HttpClient client, string uri)
{
TimeSpan delay = TimeSpan.FromSeconds(2);
for (int i = 0; i < 4; i++)
{
try
{
return await client.GetStringAsync(uri);
}
catch
{
}
await Task.Delay(delay);
}
return await client.GetStringAsync(uri);
}
.NET Meetup
async Task<string> DownloadStringWithRetries(HttpClient client, string uri)
{
TimeSpan delay = TimeSpan.FromSeconds(1);
for (int i = 0; i < 4; i++)
{
try
{
return await client.GetStringAsync(uri);
}
catch
{
}
await Task.Delay(delay);
delay = delay + delay;
}
return await client.GetStringAsync(uri);
}
Отмена
.NET Meetup
Отмена
● По таймеру
● Из вызывающего потока
● Игнорировать результат выполнения потока
.NET Meetup
Отмена
.NET Meetup
void IssueCancelRequest()
{
using var cts = new CancellationTokenSource();
var task = CancelableMethodAsync(cts.Token);
...
cts.Cancel();
}
.NET Meetup
async Task IssueCancelRequestAsync()
{
using var cts = new CancellationTokenSource();
var task = CancelableMethodAsync(cts.Token);
...
cts.Cancel();
try
{
await task; // операция выполнилась успешно до запроса на завершение
}
catch (OperationCanceledException)
{
// операция была отменена
}
catch (Exception)
{
// операция завершилась с другой ошибкой до отмены
}
}
Ожидание отмены
.NET Meetup
public void CancelableMethod(CancellationToken cancellationToken)
{
for (int i = 0; i < 100000; i++)
{
// some work here
Thread.Sleep(1);
if (i % 1000 == 0)
cancellationToken.ThrowIfCancellationRequested();
}
}
Отмена по таймауту
● Конкурентный поток с фиксированным временем
выполнения
● CancellationToken
.NET Meetup
Таймаут конкурентным потоком
.NET Meetup
async Task<string> DownloadStringWithTimeout(HttpClient client, string uri)
{
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
Task<string> downloadTask = client.GetStringAsync(uri);
Task timeoutTask = Task.Delay(Timeout.InfiniteTimeSpan, cts.Token);
Task completedTask = await Task.WhenAny(downloadTask, timeoutTask);
if (completedTask == timeoutTask)
return null;
return await downloadTask;
}
CancellationToken таймаут
.NET Meetup
async Task IssueTimeoutAsync()
{
using var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
cts.CancelAfter(TimeSpan.FromSeconds(5));
await Task.Delay(TimeSpan.FromSeconds(10), token);
}
Комбинирование отмены
.NET Meetup
async Task<HttpResponseMessage> GetWithTimeoutAsync(HttpClient client,
string url, CancellationToken cancellationToken)
{
using CancellationTokenSource cts = CancellationTokenSource
.CreateLinkedTokenSource(cancellationToken);
cts.CancelAfter(TimeSpan.FromSeconds(2));
CancellationToken combinedToken = cts.Token;
return await client.GetAsync(url, combinedToken);
}
Прогресс
.NET Meetup
Прогресс
Используем IProgress<T> и Progress<T>.
Async-метод получает аргумент IProgress<T>;
T - тип прогресса, о котором хотим сообщать.
.NET Meetup
.NET Meetup
async Task CallMyMethodAsync()
{
var progress = new Progress<double>();
progress.ProgressChanged += (sender, args) =>
{
...
};
await MyMethodAsync(progress);
}
async Task MyMethodAsync(IProgress<double> progress = null)
{
bool done = false;
double percentComplete = 0;
while (!done)
{
...
progress?.Report(percentComplete);
}
}
Вопрос к аудитории
.NET Meetup
Вопрос к аудитории
Сколько потоков ждут ответа от устройства?
.NET Meetup
private async void Button_Click(object sender, RoutedEventArgs e)
{
byte[] data = ...
await someDevice.WriteAsync(data, 0, data.Length);
}
.NET Meetup
There is no spoon
.NET Meetup
There is no thread
.NET Meetup
Thank you
For your attention!
Any Questions?
.NET Meetup

More Related Content

What's hot

Async clinic by by Sergey Teplyakov
Async clinic by by Sergey TeplyakovAsync clinic by by Sergey Teplyakov
Async clinic by by Sergey TeplyakovAlex Tumanoff
 
JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)Mikhail Davydov
 
Контроль качества верстки или как начать делать Makeup
Контроль качества верстки или как начать делать MakeupКонтроль качества верстки или как начать делать Makeup
Контроль качества верстки или как начать делать MakeupTimophy Chaptykov
 
RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)Noveo
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularizationIvan Krylov
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey TeplyakovAlex Tumanoff
 
Производительность open source решений
Производительность open source решенийПроизводительность open source решений
Производительность open source решенийVladimir Sitnikov
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerAnton Arhipov
 
Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Oleksii Okhrymenko
 
Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2Oleksii Okhrymenko
 
Codefest-2015 Reactive Streams
Codefest-2015 Reactive StreamsCodefest-2015 Reactive Streams
Codefest-2015 Reactive StreamsAlexey Romanchuk
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Sergey Platonov
 
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья СтусьПолный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья СтусьMail.ru Group
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMSergey Platonov
 
Mike ponomarenko java17-fork-v1.2
Mike ponomarenko java17-fork-v1.2Mike ponomarenko java17-fork-v1.2
Mike ponomarenko java17-fork-v1.2Alex Tumanoff
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаAnton Arhipov
 
Практика использования Dependency Injection
Практика использования Dependency InjectionПрактика использования Dependency Injection
Практика использования Dependency InjectionPlatonov Sergey
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Yauheni Akhotnikau
 
Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016Кирилл Толкачёв
 

What's hot (20)

Async clinic by by Sergey Teplyakov
Async clinic by by Sergey TeplyakovAsync clinic by by Sergey Teplyakov
Async clinic by by Sergey Teplyakov
 
JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)JavaScript. Event Loop and Timers (in russian)
JavaScript. Event Loop and Timers (in russian)
 
Контроль качества верстки или как начать делать Makeup
Контроль качества верстки или как начать делать MakeupКонтроль качества верстки или как начать делать Makeup
Контроль качества верстки или как начать делать Makeup
 
RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)RxJava+RxAndroid (Lecture 20 – rx java)
RxJava+RxAndroid (Lecture 20 – rx java)
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
Deep Dive C# by Sergey Teplyakov
Deep Dive  C# by Sergey TeplyakovDeep Dive  C# by Sergey Teplyakov
Deep Dive C# by Sergey Teplyakov
 
Производительность open source решений
Производительность open source решенийПроизводительность open source решений
Производительность open source решений
 
JPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profilerJPoint 2016 - Etudes of DIY Java profiler
JPoint 2016 - Etudes of DIY Java profiler
 
Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2Превышаем скоростные лимиты с Angular 2
Превышаем скоростные лимиты с Angular 2
 
Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2Превышаем скоросные лимиты с Angular 2
Превышаем скоросные лимиты с Angular 2
 
Codefest-2015 Reactive Streams
Codefest-2015 Reactive StreamsCodefest-2015 Reactive Streams
Codefest-2015 Reactive Streams
 
Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++Борис Сазонов, RAII потоки и CancellationToken в C++
Борис Сазонов, RAII потоки и CancellationToken в C++
 
UA Mobile 2012
UA Mobile 2012UA Mobile 2012
UA Mobile 2012
 
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья СтусьПолный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
Полный цикл тестирования React-приложений, Алексей Андросов и Наталья Стусь
 
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVMДмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
Дмитрий Кашицын, Троллейбус из буханки: алиасинг и векторизация в LLVM
 
Mike ponomarenko java17-fork-v1.2
Mike ponomarenko java17-fork-v1.2Mike ponomarenko java17-fork-v1.2
Mike ponomarenko java17-fork-v1.2
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчика
 
Практика использования Dependency Injection
Практика использования Dependency InjectionПрактика использования Dependency Injection
Практика использования Dependency Injection
 
Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?Для чего мы делали свой акторный фреймворк и что из этого вышло?
Для чего мы делали свой акторный фреймворк и что из этого вышло?
 
Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016Эволюционный дизайн. Joker Students Day 2016
Эволюционный дизайн. Joker Students Day 2016
 

Similar to Wild Async .NET world: AID Kit for boy-scouts

C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.Igor Shkulipa
 
Асинхронные вызовы в .NET
Асинхронные вызовы в .NETАсинхронные вызовы в .NET
Асинхронные вызовы в .NETBonart
 
Простой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NETПростой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NETMikhail Shcherbakov
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееGetDev.NET
 
Дополненная Реальность в Облаке
Дополненная Реальность в ОблакеДополненная Реальность в Облаке
Дополненная Реальность в ОблакеGeeksLab Odessa
 
C# Desktop. Занятие 12.
C# Desktop. Занятие 12.C# Desktop. Занятие 12.
C# Desktop. Занятие 12.Igor Shkulipa
 
Android - 11 - Multithreading
Android - 11 - MultithreadingAndroid - 11 - Multithreading
Android - 11 - MultithreadingNoveo
 
8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threadsMERA_school
 
МАИ, Сети ЭВМ, Лекция №5
МАИ, Сети ЭВМ, Лекция №5МАИ, Сети ЭВМ, Лекция №5
МАИ, Сети ЭВМ, Лекция №5Dima Dzuba
 
Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"Fwdays
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Noveo
 
Java весна 2014 лекция 5
Java весна 2014 лекция 5Java весна 2014 лекция 5
Java весна 2014 лекция 5Technopark
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1Michael Karpov
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программированияguestfc8ae0
 
инструменты параллельного программирования
инструменты параллельного программированияинструменты параллельного программирования
инструменты параллельного программированияAlexander Petrov
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй этоRoman Dvornov
 
Froglogic Squish
Froglogic Squish Froglogic Squish
Froglogic Squish SQALab
 
Asynchrony and coroutines
Asynchrony and coroutinesAsynchrony and coroutines
Asynchrony and coroutinescorehard_by
 

Similar to Wild Async .NET world: AID Kit for boy-scouts (20)

Async
AsyncAsync
Async
 
Luxoft async.net
Luxoft async.netLuxoft async.net
Luxoft async.net
 
C# Desktop. Занятие 16.
C# Desktop. Занятие 16.C# Desktop. Занятие 16.
C# Desktop. Занятие 16.
 
Асинхронные вызовы в .NET
Асинхронные вызовы в .NETАсинхронные вызовы в .NET
Асинхронные вызовы в .NET
 
Простой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NETПростой и кросс-платформенный WEB-сервер на .NET
Простой и кросс-платформенный WEB-сервер на .NET
 
C# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущееC# 5.0. Взгляд в будущее
C# 5.0. Взгляд в будущее
 
Дополненная Реальность в Облаке
Дополненная Реальность в ОблакеДополненная Реальность в Облаке
Дополненная Реальность в Облаке
 
C# Desktop. Занятие 12.
C# Desktop. Занятие 12.C# Desktop. Занятие 12.
C# Desktop. Занятие 12.
 
Android - 11 - Multithreading
Android - 11 - MultithreadingAndroid - 11 - Multithreading
Android - 11 - Multithreading
 
8. java lecture threads
8. java lecture threads8. java lecture threads
8. java lecture threads
 
МАИ, Сети ЭВМ, Лекция №5
МАИ, Сети ЭВМ, Лекция №5МАИ, Сети ЭВМ, Лекция №5
МАИ, Сети ЭВМ, Лекция №5
 
Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"Никита Галкин "Testing in Node.js World"
Никита Галкин "Testing in Node.js World"
 
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
Многопоточность, работа с сетью (Lecture 12 – multithreading, network)
 
Java весна 2014 лекция 5
Java весна 2014 лекция 5Java весна 2014 лекция 5
Java весна 2014 лекция 5
 
20090720 hpc exercise1
20090720 hpc exercise120090720 hpc exercise1
20090720 hpc exercise1
 
паттерны программирования
паттерны программированияпаттерны программирования
паттерны программирования
 
инструменты параллельного программирования
инструменты параллельного программированияинструменты параллельного программирования
инструменты параллельного программирования
 
Инструментируй это
Инструментируй этоИнструментируй это
Инструментируй это
 
Froglogic Squish
Froglogic Squish Froglogic Squish
Froglogic Squish
 
Asynchrony and coroutines
Asynchrony and coroutinesAsynchrony and coroutines
Asynchrony and coroutines
 

More from HYS Enterprise

Magic of web components
Magic of web componentsMagic of web components
Magic of web componentsHYS Enterprise
 
“ASP.NET Core. Features and architecture”
“ASP.NET Core. Features and architecture” “ASP.NET Core. Features and architecture”
“ASP.NET Core. Features and architecture” HYS Enterprise
 
How to create a perfect CV and make a good impression at an interview
How to create a perfect CV and make a good impression at an interviewHow to create a perfect CV and make a good impression at an interview
How to create a perfect CV and make a good impression at an interviewHYS Enterprise
 
Top soft skills to get a job
Top soft skills to get a jobTop soft skills to get a job
Top soft skills to get a jobHYS Enterprise
 
Contract testing. Getting started with Pact IO.
Contract testing. Getting started with Pact IO.Contract testing. Getting started with Pact IO.
Contract testing. Getting started with Pact IO.HYS Enterprise
 
Testing strategies in a microservices architecture. Independence vs integration
Testing strategies in a microservices architecture.  Independence vs integrationTesting strategies in a microservices architecture.  Independence vs integration
Testing strategies in a microservices architecture. Independence vs integrationHYS Enterprise
 
Leonid Sushenko "Pro scrum"
Leonid Sushenko "Pro scrum"Leonid Sushenko "Pro scrum"
Leonid Sushenko "Pro scrum"HYS Enterprise
 
"Test Design Techniques"
"Test Design Techniques" "Test Design Techniques"
"Test Design Techniques" HYS Enterprise
 
Essentials soft skills for a developer
Essentials soft skills for a developerEssentials soft skills for a developer
Essentials soft skills for a developerHYS Enterprise
 
“Tips&Tricks&Antitricks with .Net Core backend in GameDev”
“Tips&Tricks&Antitricks with .Net Core backend in GameDev”“Tips&Tricks&Antitricks with .Net Core backend in GameDev”
“Tips&Tricks&Antitricks with .Net Core backend in GameDev”HYS Enterprise
 
"Dealing with legacy code"
"Dealing with legacy code""Dealing with legacy code"
"Dealing with legacy code"HYS Enterprise
 
“QA job interview: life hacks and scripts for success”
“QA job interview: life hacks and scripts for success”“QA job interview: life hacks and scripts for success”
“QA job interview: life hacks and scripts for success”HYS Enterprise
 
Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”
Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”
Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”HYS Enterprise
 
Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."
Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."
Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."HYS Enterprise
 
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."HYS Enterprise
 
Я твой Expected Result шатал
Я твой Expected Result шаталЯ твой Expected Result шатал
Я твой Expected Result шаталHYS Enterprise
 
“Elasticsearch for .NET developers”
“Elasticsearch for .NET developers”  “Elasticsearch for .NET developers”
“Elasticsearch for .NET developers” HYS Enterprise
 
“Microservices: how to avoid making the same mistake twice.”
“Microservices: how to avoid making the same mistake twice.”“Microservices: how to avoid making the same mistake twice.”
“Microservices: how to avoid making the same mistake twice.”HYS Enterprise
 
Cheap and Cheerful: Useful Tools for Fast Development of Ready-Made Solutions
Cheap and Cheerful: Useful Tools for Fast Development of Ready-Made SolutionsCheap and Cheerful: Useful Tools for Fast Development of Ready-Made Solutions
Cheap and Cheerful: Useful Tools for Fast Development of Ready-Made SolutionsHYS Enterprise
 

More from HYS Enterprise (20)

Magic of web components
Magic of web componentsMagic of web components
Magic of web components
 
“ASP.NET Core. Features and architecture”
“ASP.NET Core. Features and architecture” “ASP.NET Core. Features and architecture”
“ASP.NET Core. Features and architecture”
 
How to create a perfect CV and make a good impression at an interview
How to create a perfect CV and make a good impression at an interviewHow to create a perfect CV and make a good impression at an interview
How to create a perfect CV and make a good impression at an interview
 
Top soft skills to get a job
Top soft skills to get a jobTop soft skills to get a job
Top soft skills to get a job
 
Saga pattern
Saga patternSaga pattern
Saga pattern
 
Contract testing. Getting started with Pact IO.
Contract testing. Getting started with Pact IO.Contract testing. Getting started with Pact IO.
Contract testing. Getting started with Pact IO.
 
Testing strategies in a microservices architecture. Independence vs integration
Testing strategies in a microservices architecture.  Independence vs integrationTesting strategies in a microservices architecture.  Independence vs integration
Testing strategies in a microservices architecture. Independence vs integration
 
Leonid Sushenko "Pro scrum"
Leonid Sushenko "Pro scrum"Leonid Sushenko "Pro scrum"
Leonid Sushenko "Pro scrum"
 
"Test Design Techniques"
"Test Design Techniques" "Test Design Techniques"
"Test Design Techniques"
 
Essentials soft skills for a developer
Essentials soft skills for a developerEssentials soft skills for a developer
Essentials soft skills for a developer
 
“Tips&Tricks&Antitricks with .Net Core backend in GameDev”
“Tips&Tricks&Antitricks with .Net Core backend in GameDev”“Tips&Tricks&Antitricks with .Net Core backend in GameDev”
“Tips&Tricks&Antitricks with .Net Core backend in GameDev”
 
"Dealing with legacy code"
"Dealing with legacy code""Dealing with legacy code"
"Dealing with legacy code"
 
“QA job interview: life hacks and scripts for success”
“QA job interview: life hacks and scripts for success”“QA job interview: life hacks and scripts for success”
“QA job interview: life hacks and scripts for success”
 
Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”
Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”
Evgeniy Burak (HYS Enterprise): “Spring Data REST or intellectual job VS manual”
 
Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."
Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."
Dmitriy Mustafin (HYS Enterprise) "Web UI for Back-end developer."
 
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
Nikolay Tsyb (HYS Enterprise) "Immortal system as a piece of cake."
 
Я твой Expected Result шатал
Я твой Expected Result шаталЯ твой Expected Result шатал
Я твой Expected Result шатал
 
“Elasticsearch for .NET developers”
“Elasticsearch for .NET developers”  “Elasticsearch for .NET developers”
“Elasticsearch for .NET developers”
 
“Microservices: how to avoid making the same mistake twice.”
“Microservices: how to avoid making the same mistake twice.”“Microservices: how to avoid making the same mistake twice.”
“Microservices: how to avoid making the same mistake twice.”
 
Cheap and Cheerful: Useful Tools for Fast Development of Ready-Made Solutions
Cheap and Cheerful: Useful Tools for Fast Development of Ready-Made SolutionsCheap and Cheerful: Useful Tools for Fast Development of Ready-Made Solutions
Cheap and Cheerful: Useful Tools for Fast Development of Ready-Made Solutions
 

Wild Async .NET world: AID Kit for boy-scouts

  • 1. Wild Async .NET world By Vladimir Garbar .NET Meetup Play hys-enterprise.com
  • 2. My experience .NET Developer Team Lead @ HYS Enterprise .NET Meetup
  • 3. HYS Enterprise is a Dutch software development company with more than 200 talented engineers from all over the world hys-enterprise.com UkraineNetherlands
  • 4. Wild Async .NET world AID Kit for boy scouts .NET Meetup
  • 5. План 1. Общие понятия 2. Async + Await 3. Практики .NET Meetup
  • 8. Конкурентность Полезность: - В любой ситуации, когда приложение должно делать что-то одно во время работы над чем-то другим. - Для конечного пользователя, чтобы реагировать на ввод данных пользователем во время записи в базу данных. - Серверные приложения используют конкурентность для реакции на второй запрос в ходе завершения первого запроса. .NET Meetup
  • 9. Многопоточность Форма конкурентности, использующая несколько потоков выполнения .NET Meetup
  • 10. Параллельная обработка Выполнение большого объема работы за счет распределения ее между несколькими потоками, выполняемыми одновременно .NET Meetup
  • 11. Асинхронное программирование Разновидность конкурентности, использующая обещания или обратные вызовы для предотвращения создания лишних потоков .NET Meetup
  • 13. Преимущества ● Уменьшает сложность ● Улучшает читаемость .NET Meetup
  • 18. Горизонтальная масштабируемость Добавление количества серверов: - RESTful - Распределенные базы данных - Кэширование данных - Отсутствие сессии .NET Meetup
  • 19. Вертикальная масштабируемость Улучшение качеств текущих серверов: - Больше RAM - Быстрые HDD - Больше CPU Cores - Более оптимальное использование ресурсов - Оптимальное использование потоков - Освобождение потока как можно скорее .NET Meetup
  • 20. Параллельная обработка Использует потоки, которые иначе бы простаивали .NET Meetup
  • 22. Подводные камни ● Проблемы с общим доступом ● Восстановление контекста ● Deadlock ● Сложно использовать .NET Meetup
  • 24. Async ● Добавляется в объявление метода. ● Разрешает использование ключевого слова await внутри этого метода. ● Дает инструкцию компилятору сгенерировать для этого метода конечный автомат .NET Meetup
  • 25. Await ● Выполняет асинхронное ожидание по своему аргументу. Сначала проверяет, завершилась ли операция: если да, то метод продолжает выполняться синхронно. ● В противном случае await приостанавливает async-метод и возвращает незавершенную задачу. ● Когда операция завершится позднее, метод async продолжает выполнение. .NET Meetup
  • 26. Async-метод Может рассматриваться как состоящий из нескольких синхронных частей, разделенных командами await. .NET Meetup
  • 27. Async-метод Первая синхронная часть выполняется в потоке, который вызвал метод. Все синхронные части пытаются возобновить продолжение в исходном контексте. Если вызвать метод DoSomethingAsync из UI-потока, каждая из его синхронных частей будет выполняться в этом UI-потоке, но если вызвать его из потока из пула потоков, то каждая из синхронных частей будет выполняться в любом потоке из пула потоков. .NET Meetup
  • 29. Взаимоблокировка .NET Meetup void Deadlock() { Task task = WaitAsync(); // Синхронное блокирование с ожиданием завершения async метода. task.Wait(); } async Task WaitAsync() { // await сохранит текущий контекст await Task.Delay(TimeSpan.FromSeconds(1)); // попытается возобновить метод в этой точке с этим контекстом. }
  • 31. Взаимоблокировка: Решение .NET Meetup void Deadlock() { Task task = WaitAsync(); // Синхронное блокирование с ожиданием завершения async метода. task.Wait(); } async Task WaitAsync() { await Task.Delay(TimeSpan.FromSeconds(1)) .ConfigureAwait(false); }
  • 32. Взаимоблокировка: Лучшее .NET Meetup async void Deadlock() { Task task = await WaitAsync(); } async Task WaitAsync() { // await сохранит текущий контекст await Task.Delay(TimeSpan.FromSeconds(1)); // попытается возобновить метод в этой точке с этим контекстом. }
  • 33. Синхронизация контекста Хорошей практикой считается вызывать ConfigureAwait в базовых “библиотечных” методах и возобновлять контекст только тогда, когда потребуется - в ваших внешних методах “пользовательского интерфейса”. .NET Meetup
  • 34. Синхронизация контекста ConfigureAwait(false) конфигурирует Task так, что возвращение из await не обязательно должно выполняться в вызывающем контексте. Использовалось для избегания Deadlocks. И для того, чтобы не ожидать вызывающий контекст. .NET Meetup
  • 35. Синхронизация контекста ASP.NET Core не имеет синхронизации контекста - Используется Thread pool - Улучшает производительность - Легче писать async code. Не ответственность разработчика - Task.Result больше не приводит к Deadlock, но приводит к блокировке вызывающего потока .NET Meetup
  • 36. Синхронизация контекста ConfigureAwait(false) больше не требуется для .NET Core Но желательно для .NET Standard 2.0, который может работать под .NET Framework .NET Meetup
  • 38. Синхронный код + асинхронный .NET Meetup
  • 39. Синхронный код + асинхронный .NET Meetup async Task<string> DownloadStringAsync(HttpClient client, string uri) { return await client.GetStringAsync(uri); }
  • 40. Синхронный код + асинхронный .NET Meetup string DownloadString(HttpClient client, string uri) { return await client.GetStringAsync(uri); // Error! }
  • 41. Синхронный код + асинхронный .NET Meetup string DownloadString(HttpClient client, string uri) { return client.GetStringAsync(uri).Result; }
  • 42. Синхронный код + асинхронный .NET Meetup string DownloadString(HttpClient client, string uri) { return client.GetStringAsync(uri).GetAwaiter().GetResult(); }
  • 43. Синхронный код + асинхронный .NET Meetup async Task<string> DownloadStringAsync(HttpClient client, string uri) { return await client.GetStringAsync(uri); }
  • 44. Синхронный код + асинхронный .NET Meetup async Task<string> DownloadStringAsync(HttpClient client, string uri) { return await client.GetStringAsync(uri); }
  • 45. Синхронный код + асинхронный .NET Meetup Task<string> DownloadStringAsync(HttpClient client, string uri) { return client.GetStringAsync(uri); }
  • 46. Синхронный код + асинхронный .NET Meetup async Task<string> DownloadStringAsync(HttpClient client, string uri) { return await client.GetStringAsync(uri); }
  • 47. Синхронный код + асинхронный .NET Meetup async Task<string> DownloadStringAsync(HttpClient client, string uri) { try { return await client.GetStringAsync(uri); } catch(Exception) { // обработаем ошибку } }
  • 48. Синхронный код + асинхронный .NET Meetup Task<string> DownloadStringAsync(HttpClient client, string uri) { try { return client.GetStringAsync(uri); } catch(Exception) { // сюда не попадем :( } }
  • 49. Синхронный код + асинхронный .NET Meetup async Task<string> DownloadStringAsync(HttpClient client, string uri) { try { return await client.GetStringAsync(uri); } catch(Exception) { // обработаем ошибку } }
  • 50. Синхронный код + асинхронный .NET Meetup Task<string> DownloadStringAsync(HttpClient client, string uri) { return client.GetStringAsync(uri); }
  • 51. Синхронный код + асинхронный .NET Meetup Task DoSomethingAsync() { return Task.CompletedTask; }
  • 52. Синхронный код + асинхронный .NET Meetup Task<int> GetValueAsync() { return Task.FromResult(200); }
  • 53. Синхронный код + асинхронный .NET Meetup Task<int> GetValueAsync(CancellationToken cancellationToken) { if (cancellationToken.IsCancellationRequested) return Task.FromCanceled<int>(cancellationToken); return Task.FromResult(200); }
  • 54. Синхронный код + асинхронный .NET Meetup Task<T> ExceptionAsync<T>() { return Task.FromException<T>(new NotImplementedException()); }
  • 55. Синхронный код + асинхронный .NET Meetup Task DoSomethingAsync() { try { DoSomething(); return Task.CompletedTask; } catch (Exception ex) { return Task.FromException(ex); } }
  • 56. Async Async метод возвращает: ● void ● Task, Task<TResult> ● ValueTask, ValueTask<T> ● IAsyncEnumerable<T>, IAsyncEnumerator<T> .NET Meetup
  • 57. async void ● Только для event handlers ● Тяжело обрабатывать ошибки ● Сложно тестировать ● Нелегко оповещать вызывающий код о статусе своего выполнения .NET Meetup
  • 58. ValueTask ● Cокращает затраты памяти, если результат в основном является синхронным. ● Например, если результат может быть прочитан из кэша в памяти. .NET Meetup
  • 59. ValueTask .NET Meetup async ValueTask<int> GetOrderAsync() { if (_cachedOrder != 0) return _cachedOrder; _cachedOrder = await GetOrderFromStorageAsync(); return _cachedOrder; }
  • 60. ValueTask: недостатки ● ValueTask или ValueTask<T> может ожидаться только один раз ● Можно вызвать AsTask только один раз. ● Синхронная загрузка результата из Task<T> блокирует вызывающий поток до завершения задачи; ValueTask<T> таких гарантий не дает. ● Синхронное получение результатов от ValueTask или ValueTask<T> ● может быть выполнено только один раз, после завершения ValueTask. .NET Meetup
  • 61. IAsyncEnumerable<T> Работает так же, как и IEnumerable<T>, только асинхронно получает каждый следующий элемент. .NET Meetup
  • 62. IAsyncEnumerable<T> .NET Meetup async IAsyncEnumerable<int> GetValuesAsync() { await Task.Delay(1000); // сложные расчеты или загрузка из сети yield return 1; await Task.Delay(1000); // сложные расчеты или загрузка из сети yield return 2; }
  • 63. IAsyncEnumerable<T> .NET Meetup IAsyncEnumerable<string> GetValuesAsync(HttpClient client); async Task ProcessValueAsync(HttpClient client) { await foreach (string value in GetValuesAsync(client)) { Console.WriteLine(value); } }
  • 64. IAsyncEnumerable<T> .NET Meetup IAsyncEnumerable<string> GetValuesAsync(HttpClient client); async Task ProcessValueAsync(HttpClient client) { await foreach (string value in GetValuesAsync(client)) { await Task.Delay(100); // асинхронно обрабатываем элемент Console.WriteLine(value); } }
  • 65. IAsyncEnumerable<T> .NET Meetup IAsyncEnumerable<string> GetValuesAsync(HttpClient client); async Task ProcessValueAsync(HttpClient client) { await foreach (string value in GetValuesAsync(client).ConfigureAwait(false))) { await Task.Delay(100).ConfigureAwait(false)); // асинхронно обрабатываем элемент Console.WriteLine(value); } }
  • 66. .NET Meetup async IAsyncEnumerable<string> GetValuesAsync(HttpClient client) { int offset = 0; const int limit = 10; while (true) { var result = await client.GetStringAsync($"https://my.com/api/values?offset={offset}&limit={limit}"); string[] items = result.Split('n'); foreach (string item in items) yield return item; if (items.Length < limit) break; // елементов меньше - последняя страница offset += limit; } }
  • 68. Ожидание нескольких задач .NET Meetup Task task1 = Task.Delay(TimeSpan.FromSeconds(3)); Task task2 = Task.Delay(TimeSpan.FromSeconds(2)); Task task3 = Task.Delay(TimeSpan.FromSeconds(1)); await Task.WhenAll(task1, task2, task3);
  • 69. Ожидание нескольких задач .NET Meetup Task<int> task1 = Task.FromResult(3); Task<int> task2 = Task.FromResult(2); Task<int> task3 = Task.FromResult(1); int[] results = await Task.WhenAll(task1, task2, task3);
  • 70. .NET Meetup async Task ProcessTasksAsync() { Task<string> taskA = DelayAndReturnAsync(3, "medium"); Task<string> taskB = DelayAndReturnAsync(5, "slow"); Task<string> taskC = DelayAndReturnAsync(1, "fast"); Task<string>[] tasks = new[] { taskA, taskB, taskC }; foreach (var task in tasks) { var result = await task; Results.Add(result); } } async Task<string> DelayAndReturnAsync(int delay, string value) { await Task.Delay(TimeSpan.FromSeconds(delay)); return value; }
  • 71. .NET Meetup async Task ProcessTasksAsync() { Task<string> taskA = DelayAndReturnAsync(3, "medium"); Task<string> taskB = DelayAndReturnAsync(5, "slow"); Task<string> taskC = DelayAndReturnAsync(1, "fast"); Task<string>[] tasks = new[] { taskA, taskB, taskC }; foreach (var task in tasks) { var result = await task; Results.Add(result); } } async Task<string> DelayAndReturnAsync(int delay, string value) { await Task.Delay(TimeSpan.FromSeconds(delay)); return value; } "medium" "slow" "fast"
  • 72. .NET Meetup async Task ProcessTasksAsync() { Task<string> taskA = DelayAndReturnAsync(3, "medium"); Task<string> taskB = DelayAndReturnAsync(5, "slow"); Task<string> taskC = DelayAndReturnAsync(1, "fast"); Task<string>[] tasks = new[] { taskA, taskB, taskC }; Task<string>[] processingTasks = tasks.Select(async t => { var result = await t; Result.Add(result); return result; }).ToArray(); await Task.WhenAll(processingTasks); } "fast" "medium" "slow"
  • 74. Синхронизация Если в вашем приложении используется конкурентность, следует остерегаться ситуаций, в которых один блок кода должен обновлять данные, пока другой код обращается к тем же данным. Столкнувшись с подобной ситуацией, необходимо синхронизировать доступ к данным .NET Meetup
  • 75. Синхронизация Основные виды синхронизации: ● передачи данных ● защиты данных .NET Meetup
  • 76. Синхронизация для защиты Необходима при выполнении всех трех условий: 1. Несколько частей кода выполняются одновременно 2. Общие данные 3. Обновление данных .NET Meetup
  • 77. Синхронизация для защиты Цель защиты данных заключается в том, чтобы каждая часть кода имела целостное представление данных. Если одна часть кода обновляет данные, вы можете воспользоваться синхронизацией, чтобы обновления воспринимались как атомарные для остальных компонентов системы. .NET Meetup
  • 78. Нужна синхронизации для value? .NET Meetup async Task<int> MyMethodAsync() { int value = 10; await Task.Delay(TimeSpan.FromSeconds(1)); value += 1; await Task.Delay(TimeSpan.FromSeconds(1)); value += 1; await Task.Delay(TimeSpan.FromSeconds(1)); return await Task.FromResult(value); }
  • 79. Нужна синхронизации для value? .NET Meetup async Task<int> MyMethodAsync() { int value = 10; await Task.Delay(TimeSpan.FromSeconds(1)); value += 1; await Task.Delay(TimeSpan.FromSeconds(1)); value += 1; await Task.Delay(TimeSpan.FromSeconds(1)); return await Task.FromResult(value); } Нет
  • 80. Нужна синхронизации для value? .NET Meetup private int value; async Task ModifyValueAsync() { var originalValue = value; await Task.Delay(TimeSpan.FromSeconds(1)); value = originalValue + 1; }
  • 81. Нужна синхронизации для value? .NET Meetup private int value; async Task ModifyValueAsync() { var originalValue = value; await Task.Delay(TimeSpan.FromSeconds(1)); value = originalValue + 1; } Да
  • 82. Lock блокировка .NET Meetup private readonly object _mutex = new object(); private int _value; public void Increment() { lock (_mutex) { _value = _value + 1; } }
  • 83. Lock блокировка .NET Meetup ● Ограничьте видимость блокировки: private объект, не string, не this ● Защищать только то, что должно быть защищено ● Минимальный объем кода, защищенного блокировкой: минимум блокирующих вызовов в lock ● Никакого произвольного кода при удержании блокировки: не инициируйте события, не вызывайте делегаты и другие методы
  • 85. .NET Meetup private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1); private int _value; public async Task DelayAndIncrementAsync() { await _mutex.WaitAsync(); try { int oldValue = _value; await Task.Delay(TimeSpan.FromSeconds(oldValue)); _value = oldValue + 1; } finally { _mutex.Release(); } }
  • 86. Синхронизация передачи данных Синхронизация при передаче данных используется в тех случаях, когда один блок кода должен оповестить другой блок кода о некотором условии (например, о поступлении нового сообщения) .NET Meetup
  • 87. Блокировка через сигналы .NET Meetup private readonly ManualResetEventSlim _initialized = new ManualResetEventSlim(); private int _value; public int ReturnResultFromThreadA() { _initialized.Wait(); return _value; } public void InitializeFromThreadB() { _value = 13; _initialized.Set(); }
  • 88. Async блокировка через сигналы .NET Meetup private readonly TaskCompletionSource<object> _initialized = new TaskCompletionSource<object>(); private int _value; public async Task<int> WaitForInitializationAsync() { await _initialized.Task; return _value1 + 1; } public void Initialize() { _value = 5; _initialized.TrySetResult(null); }
  • 90. Исключения .NET Meetup async Task TestAsync() { try { await ThrowExceptionAsync(); } catch (InvalidOperationException) { } } async Task ThrowExceptionAsync() { await Task.Delay(TimeSpan.FromSeconds(5)); throw new InvalidOperationException("Error"); }
  • 91. .NET Meetup async Task ObserveOneExceptionAsync() { var task1 = ThrowNotImplementedExceptionAsync(); var task2 = ThrowInvalidOperationExceptionAsync(); try { await Task.WhenAll(task1, task2); } catch (Exception ex) { // Какие exception будут здесь? } } async Task ThrowNotImplementedExceptionAsync() { throw new NotImplementedException(); } async Task ThrowInvalidOperationExceptionAsync() { throw new InvalidOperationException(); }
  • 92. .NET Meetup async Task ObserveOneExceptionAsync() { var task1 = ThrowNotImplementedExceptionAsync(); var task2 = ThrowInvalidOperationExceptionAsync(); Task allTasks = Task.WhenAll(task1, task2); try { await allTasks; } catch (Exception ex) { AggregateException allExceptions = allTasks.Exception; } } async Task ThrowNotImplementedExceptionAsync() { throw new NotImplementedException(); } async Task ThrowInvalidOperationExceptionAsync() { throw new InvalidOperationException(); }
  • 93. async Task<MultipartFormDataStreamProvider> Read(HttpContent content) { var multipartContentProvider = new MultipartFormDataStreamProvider(_tmpFolderPath); var task = content.ReadAsMultipartAsync(multipartContentProvider); if (task.IsFaulted || task.IsCanceled) throw new ContentFormatException($"HTTP message is not in correct format"); return await task; } Исключения: Bad Code .NET Meetup
  • 94. .NET Meetup async Task TestAsync() { Task task = ThrowExceptionAsync(); // Исключение выдается методом и помещается в задачу try { await task; // Здесь исключение будет выдано повторно } catch (Exception) { // Здесь исключение правильно перехватывается. } } Исключения: Good Code
  • 96. Задержка Когда может понадобиться: ● В надежде, что другая операция закончилась ● Тестирование ● Повтор операции через время .NET Meetup
  • 97. .NET Meetup Задержка async Task<T> DelayResult<T>(T result, TimeSpan delay) { Thread.Sleep(delay); return await Task.FromResult(result); }
  • 98. .NET Meetup Задержка async Task<T> DelayResult<T>(T result, TimeSpan delay) { Thread.Sleep(delay); return await Task.FromResult(result); } async Task<T> DelayResult<T>(T result, TimeSpan delay) { await Task.Delay(delay); return result; }
  • 99. Задержка Повтор операции ● Без задержки ● С постоянной задержкой ● С увеличивающейся задержкой .NET Meetup
  • 100. .NET Meetup async Task<string> DownloadStringWithRetries(HttpClient client, string uri) { for (int i = 0; i < 4; i++) { try { return await client.GetStringAsync(uri); } catch { } } return await client.GetStringAsync(uri); }
  • 101. .NET Meetup async Task<string> DownloadStringWithRetries(HttpClient client, string uri) { TimeSpan delay = TimeSpan.FromSeconds(2); for (int i = 0; i < 4; i++) { try { return await client.GetStringAsync(uri); } catch { } await Task.Delay(delay); } return await client.GetStringAsync(uri); }
  • 102. .NET Meetup async Task<string> DownloadStringWithRetries(HttpClient client, string uri) { TimeSpan delay = TimeSpan.FromSeconds(1); for (int i = 0; i < 4; i++) { try { return await client.GetStringAsync(uri); } catch { } await Task.Delay(delay); delay = delay + delay; } return await client.GetStringAsync(uri); }
  • 104. Отмена ● По таймеру ● Из вызывающего потока ● Игнорировать результат выполнения потока .NET Meetup
  • 105. Отмена .NET Meetup void IssueCancelRequest() { using var cts = new CancellationTokenSource(); var task = CancelableMethodAsync(cts.Token); ... cts.Cancel(); }
  • 106. .NET Meetup async Task IssueCancelRequestAsync() { using var cts = new CancellationTokenSource(); var task = CancelableMethodAsync(cts.Token); ... cts.Cancel(); try { await task; // операция выполнилась успешно до запроса на завершение } catch (OperationCanceledException) { // операция была отменена } catch (Exception) { // операция завершилась с другой ошибкой до отмены } }
  • 107. Ожидание отмены .NET Meetup public void CancelableMethod(CancellationToken cancellationToken) { for (int i = 0; i < 100000; i++) { // some work here Thread.Sleep(1); if (i % 1000 == 0) cancellationToken.ThrowIfCancellationRequested(); } }
  • 108. Отмена по таймауту ● Конкурентный поток с фиксированным временем выполнения ● CancellationToken .NET Meetup
  • 109. Таймаут конкурентным потоком .NET Meetup async Task<string> DownloadStringWithTimeout(HttpClient client, string uri) { using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3)); Task<string> downloadTask = client.GetStringAsync(uri); Task timeoutTask = Task.Delay(Timeout.InfiniteTimeSpan, cts.Token); Task completedTask = await Task.WhenAny(downloadTask, timeoutTask); if (completedTask == timeoutTask) return null; return await downloadTask; }
  • 110. CancellationToken таймаут .NET Meetup async Task IssueTimeoutAsync() { using var cts = new CancellationTokenSource(); CancellationToken token = cts.Token; cts.CancelAfter(TimeSpan.FromSeconds(5)); await Task.Delay(TimeSpan.FromSeconds(10), token); }
  • 111. Комбинирование отмены .NET Meetup async Task<HttpResponseMessage> GetWithTimeoutAsync(HttpClient client, string url, CancellationToken cancellationToken) { using CancellationTokenSource cts = CancellationTokenSource .CreateLinkedTokenSource(cancellationToken); cts.CancelAfter(TimeSpan.FromSeconds(2)); CancellationToken combinedToken = cts.Token; return await client.GetAsync(url, combinedToken); }
  • 113. Прогресс Используем IProgress<T> и Progress<T>. Async-метод получает аргумент IProgress<T>; T - тип прогресса, о котором хотим сообщать. .NET Meetup
  • 114. .NET Meetup async Task CallMyMethodAsync() { var progress = new Progress<double>(); progress.ProgressChanged += (sender, args) => { ... }; await MyMethodAsync(progress); } async Task MyMethodAsync(IProgress<double> progress = null) { bool done = false; double percentComplete = 0; while (!done) { ... progress?.Report(percentComplete); } }
  • 116. Вопрос к аудитории Сколько потоков ждут ответа от устройства? .NET Meetup private async void Button_Click(object sender, RoutedEventArgs e) { byte[] data = ... await someDevice.WriteAsync(data, 0, data.Length); }
  • 118. There is no spoon .NET Meetup
  • 119. There is no thread .NET Meetup
  • 120. Thank you For your attention! Any Questions? .NET Meetup