dir.by  
  Поиск  
Компьютер, программы
C# (programming language)
 Асинхронное программирование в C# (теория) 
посмотрели 20771 раз
обновлено: 13 March 2019
Контекст выполнения (ExecutionContext)
Контекст выполнения (ExecutionContext) - это родительский контекст (контейнер для других конекстов), включающий все остальные контексты.
Он не имеет собственного поведения, а служит только для запоминания и передачи контекста и используется такими компонентами .NET, как класс Task.
Контекст синхронизации (SynchronizationContext)
Контекст синхронизации (SynchronizationContext) - позволяет возобновить выполнение метода в конкретном потоке.
Текущий контекст SynchronizationContext – это свойство текущего потока. Идея в том, что всякий раз, как код исполняется в каком-то специальном потоке, мы
можем получить текущий контекст синхронизации и сохранить его.
Впоследствии этот контекст можно использовать для того, чтобы продолжить исполнение кода в том потоке, в котором оно было начато.

В классе SynchronizationContext есть важный метод Post, который гарантирует, что переданный делегат будет исполняться в правильном контексте.

Важно! В момент приостановки метода при встрече оператора await текущий контекст SynchronizationContext сохраняется.
Далее, когда метод возобновляется, компилятор вставляет вызов Post, чтобы исполнение возобновилось в запомненном контексте.
Асинхронное программирование
Код называется асинхронным, если он запускает какую-то длительную операцию, но не дожидается ее завершения. Противоположностью является блокирующий код, который ничего не делает, пока операция не завершится.

К числу таких длительных операций можно отнести:
• сетевые запросы;
• доступ к диску;
• продолжительные задержки.

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

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

Часто существует лишь один поток, способный выполнить определенную задачу (например, поток пользовательского интерфейса) и, если не освободить его быстро, то приложение перестанет реагировать на действия пользователя.

Но самым важным мне кажется тот факт, что асинхронное выполнение открывает возможность для параллельных вычислений.
Что такое async?
В версии C# 5.0 Microsoft добавила механизм, предстающий в виде двух новых ключевых слов: async и await.

Механизм async встроен в компилятор и без поддержки с его стороны не мог бы быть реализован в библиотеке. Компилятор преобразовывает исходный код, то есть действует примерно по тому же принципу, что в случае лямбда-выражений и итераторов в предыдущих версиях C#.
Серверный код веб-приложения
У ASP.NET-приложений на веб-сервере нет ограничения на единственный поток, как в случае программ с пользовательским интерфейсом. И тем не менее асинхронное выполнение может оказаться весьма полезным, так как для таких приложений характерны длительные операции, особенно запросы к базе данных.

В зависимости от версии IIS может быть ограничено либо общее число потоков, обслуживающих веб-запросы, либо общее число одновременно обрабатываемых запросов. Если большая часть времени обработки запроса уходит на обращение к базе данных, то увеличение числа одновременно обрабатываемых запросов может повысить пропускную способность сервера

Помните: основная отличительная особенность асинхронного кода состоит в том, что поток, начавший длительную операцию, освобождается для других дел.
В случае ASP.NET этот поток берется из пула потоков, поэтому после запуска длительной операции он сразу же возвращается в пул и может затем использоваться для обработки других запросов. Таким образом, для обработки одного и того же количества запросов требуется меньше потоков.
Введение в класс Task
Библиотека Task Parallel Library была включена в версию .NET Framework 4.0. Важнейшим в ней является класс Task, представляющий выполняемую операцию. Его универсальный вариант, Task<T>, играет роль обещания вернуть значение (типа T), когда в будущем, по завершении операции, оно станет доступно.

Как мы увидим ниже, механизм async в C# 5.0 активно пользуется классом Task. Но и без async классом Task, а особенно его вариантом Task, можно воспользоваться при написании асинхронных программ. Для этого нужно запустить операцию, которая возвращает Task<T>, а затем вызвать метод ContinueWith для регистрации обратного вызова.
Это называется асинхронность вручную потому что используем метод ContinueWith.

Заметка на будующее:
Класс Task умеет в частности обрабатывать исключения и работать с контекстами синхронизации SynchronizationContext.
Мы увидим, что это полезно, когда требуется выполнить обратный вызов в конкретном потоке (например, в потоке пользовательского интерфейса).
Написание асинхронных методов:
1-ый шаг это пометка метода ключевым словом async.
Оно включается в сигнатуру метода точно так же, как, например, слово static.

2-ой шаг мы должны дождаться завершения скачивания, воспользовавшись ключевым словом await.
С точки зрения синтаксиса C#, await – это унарный оператор, такой же как оператор ! или оператор приведения типа (type).
Он располагается слева от выражения и означает, что нужно дождаться завершения асинхронного выполнения этого выражения.

На заметку!
Метод, помеченный ключевым словом async, автоматически не становится асинхронным.
Async-методы лишь упрощают использование других асинхронных методов. Они начинают исполняться синхронно, и так происходит до тех пор, пока не встретится вызов асинхронного метода внутри оператора await.
В этот момент сам вызывающий метод становится асинхронным.
Если же оператор await не встретится, то метод так и будет выполняться синхронно до своего завершения.
Task и await
Я говорил, что класс Task представляет выполняемую операцию, а его подкласс Task<T> – операцию, которая в будущем вернет значение типа T. Можно считать, что Task<T> – это обещание вернуть значение типа T по завершении длительной операции.
Оба класса Task и Task<T> могут представлять асинхронные операции, и оба умеют вызывать ваш код по завершении операции. Чтобы воспользоваться этой возможностью вручную, необходимо вызвать метод ContinueWith, передав ему код, который должен быть выполнен, когда длительная операция завершится. Именно так и поступает оператор await, чтобы выполнить оставшуюся часть async-метода.

Если применить await к объекту типа Task<T>, то мы получим выражение await, которое само имеет тип T.
Это означает, что результат оператора await можно присвоить переменной, которая используется далее в методе, что мы и видели в примерах.
Однако если await применяется к объекту неуниверсального класса Task, то получается предложение await, которое ничему нельзя присвоить (как и результат метода типа void). Это разумно, потому что класс Task не обещает вернуть значение в качестве результата, а представляет лишь саму операцию.
Тип значения, возвращаемого асинхронным методом
Метод, помеченный ключевым словом async, может возвращать значения трех типов:
• void
• Task
• Task, где T – некоторый тип.

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

Я провожу различие между типом возвращаемого методом значения (например, Task<string>) и типом результата, который нужен вызывающей программе (в данном случае string).
В обычных, не асинхронных, методах тип возвращаемого значения совпадает с типом результата, тогда как в асинхронных методах они различны – и это очень существенно.

Использовать тип void следует, когда вы уверены, что вызывающей программе безразлично, когда завершится операция и завершится ли она успешно.

Async-методы, возвращающие тип Task, позволяют вызывающей программе ждать завершения асинхронной операции и распространяют исключения, имевшие место при ее выполнении.

Если значение результата несущественно, то метод типа async Task предпочтительнее метода типа async void, потому что вызывающая программа получает возможность узнать о завершении операции, что упрощает упорядочение задач и обработку исключений.
Async, сигнатуры методов и интерфейсы
Ключевое слово async указывается в объявлении метода, как public или static.
Однако спецификатор async не считается частью сигнатуры метода, когда речь заходит о переопределении виртуальных методов, реализации интерфейса или вызове.
То есть в отношении переопределения методов и реализации интерфейсов, слово async полностью игнорируется.

В объявлениях методов интерфейса слово async запрещено просто потому, что в этом нет необходимости. Если в интерфейсе объявлен метод, возвращающий тип Task, то в реализующем интерфейс классе этот метод может быть помечен словом async, а может быть и не помечен – на усмотрение программиста.
Приостановка и возобновление метода
Когда поток исполнения программы доходит до оператора await, должны произойти две вещи:

1) Текущий поток должен быть освобожден, чтобы поведение программы было асинхронным. С привычной, синхронной, точки зрения это означает, что метод должен вернуть управление.

2) Когда задача Task, погруженная в оператор await, завершится, ваш метод должен продолжить выполнение с того места, где перед этим вернул управление, как будто этого возврата никогда не было.

Чтобы добиться такого поведения, метод должен приостановить выполнение, дойдя до await, и возобновить его впоследствии.
Состояние метода
Чтобы стало яснее, сколько работы должен выполнить компилятор C#, встретив в программе оператор await, я перечислю, какие именно аспекты состояния метода необходимо сохранить.

Во-первых, запоминаются все локальные переменные метода, в том числе:
• параметры метода
• все переменные, определенные в текущей области видимости
• все прочие переменные, например счетчики циклов
• переменную this, если метод не статический

В результате после возобновления метода окажутся доступны все переменные-члены класса.
Всё это сохраняется в виде объекта в куче .NET, обслуживаемой сборщиком мусора. Таким образом, встретив await, компилятор выделяет память для объекта, то есть расходует ресурсы, но в большинстве случае это не приводит к потере производительности.
C# также запоминает место, где встретился оператор await.

контекст синхронизации, который среди прочего позволяет возобновить выполнение метода в конкретном потоке.
мое: Task помогает востанавливать контекст синхронизации, перед обратным вызовом

ExecutionContext - это родительский контекст, включающий все остальные контексты. Он не имеет собственного поведения, а служит только для запоминания и передачи контекста и используется такими компонентами .NET, как класс Task.
Когда нельзя использовать await
Оператор await можно использовать почти в любом месте метода, помеченного ключевым словом async.

Оператор await может встречаться внутри блока try, но не внутри блоков catch или finally.

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

Если использовать в этой точке await, то стек окажется другим, и определить в этой ситуации поведение повторного возбуждения исключения было бы очень сложно.
Напомню, что await всегда можно поставить не внутри блока catch, а после него, для чего следует либо воспользоваться предложением return, либо завести булевскую переменную, в которой запомнить, возбуждала ли исходная операция исключение. Например, вместо такого некорректного в C# кода:

  C#  
try
{
     page = await webClient.DownloadStringTaskAsync("http://aaa.com");
}
catch (WebException)
{
     page = await webClient.DownloadStringTaskAsync("http://ooo.com");
}


можно было бы написать:

  C#  
bool failed = false;

try
{
     page = await webClient.DownloadStringTaskAsync("http://aaa.com");
}
catch (WebException)
{
     failed = true;
}

if (failed)
{
     page = await webClient.DownloadStringTaskAsync("http://ooo.com");
}
Блоки lock
Ключевое слово lock позволяет запретить другим потокам доступ к объектам, с которыми в данный момент работает текущий поток.
Поскольку асинхронный метод обычно освобождает поток, в котором начал асинхронную операцию, и через неопределенно долгое время может быть возобновлен в другом потоке, то удерживать блокировку во время выполнения await не имеет смысла.
Запоминание исключений
По завершении операции в объекте Task сохраняется информация о том, завершилась ли она успешно или с ошибкой. Получить к ней доступ проще всего с помощью свойства IsFaulted, которое равно true, если во время выполнения операции произошло исключение.
Оператор await знает об этом и повторно возбуждает исключение, хранящееся в Task.
У читателя, знакомого с системой исключений в .NET, может возникнуть вопрос, корректно ли сохраняется первоначальная трассировка стека исключения при его повторном возбуждении.

Раньше это было невозможно; каждое исключение могло быть возбуждено только один раз. Однако в .NET 4.5 это ограничение снято благодаря новому классу ExceptionDispatchInfo, который взаимодействует с классом Exception с целью запоминания трассировки стека и воспроизведения ее при повторном возбуждении.

Async-методы также знают об исключениях. Любое исключение, возбужденное, но не перехваченное в async-методе, помещается в объект Task, возвращаемый вызывающей программе. Если в этот момент вызывающая программа уже ждет объекта Task, то исключение будет возбуждено в точке ожидания. Таким образом, исключение передается вызывающей программе вместе со сформированной виртуальной трассировкой стека – точно так же, как в синхронном коде.

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

Асинхронные методы до поры исполняются синхронно Выше я уже отмечал, что async-метод становится асинхронным, только встретив вызов асинхронного метода внутри оператора await. До этого момента он работает в том потоке, в котором вызван, как обычный синхронный метод.
Использование Task для операций, требующих большого объема вычислений
Иногда длительная операция не отправляет запросов в сеть и не обращается к диску, а просто выполняет продолжительное вычисление.
Разумеется, нельзя рассчитывать на то, что поток быстро выполнит, желательно избежать зависания пользовательского интерфейса.
Для этого мы должны вернуть управление потоку пользовательского интерфейса, чтобы он мог обрабатывать другие события, а длительное вычисление производить в отдельном потоке.

Класс Task позволяет это сделать, а для обновления пользовательского интерфейса по завершении вычисления мы можем, как обычно, использовать await:

  C#  
Task t = Task.Run(() => MyLongComputation(a, b));


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

  C#  
await Task.Run(() => MyLongComputation(a, b));


Это очень простой способ выполнить некоторую работу в фоновом потоке.
Если необходим более точный контроль над тем, какой поток производит вычисления или как он планируется, в классе Task имеется статическое свойство Factory типа TaskFactory. У него есть метод StartNew с различными перегруженными вариантами для управления вычислением:

  C#  
Task t = Task.Factory.StartNew(() => MyLongComputation(a, b),
cancellationToken,
TaskCreationOptions.LongRunning,
taskScheduler);

WhenAll Ожидание завершения нескольких задач.
В разделе «Task и await» выше мы видели, как просто организовать выполнение несколько параллельных асинхронных задач, – нужно запустить их по очереди, а затем ждать завершения каждой. Потом мы узнаем, что необходимо дождаться завершения каждой задачи,
иначе можно пропустить исключения.

Для решения этой задачи можно воспользоваться методом Task.
WhenAll, который принимает несколько объектов Task и порождает агрегированную задачу, которая завершается, когда завершены все исходные задачи. Вот простейший вариант метода WhenAll (имеется также перегруженный вариант для коллекции универсальных объектов Task<T>):

Task WhenAll(IEnumerable<Task> tasks)

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

Универсальный вариант WhenAll возвращает массив, содержащий
результаты отдельных поданных на вход задач Task. Это сделано скорее для удобства, чем по необходимости, потому что доступ к исходным объектам Task сохраняется, и ничто не мешает опросить их свойство Result, так как точно известно, что все задачи уже завершены.
WhenAny Ожидание завершения любой задачи из нескольких.
Часто возникает также ситуация, когда требуется дождаться завершения первой задачи из нескольких запущенных. Например, так бывает, когда вы запрашиваете один и тот же ресурс из нескольких источников и готовы удовлетвориться первым полученным ответом.

Task<Task<T>> WhenAny(IEnumerable<Task<T>> tasks)

В ситуации, когда возможны исключения, пользоваться методом WhenAny следует с осторожностью. Если вы хотите знать обо всех исключениях, произошедших в программе,
то необходимо ждать каждую задачу, иначе некоторые исключения могут быть потеряны. Воспользоваться методом WhenAny и просто забыть об остальных задачах – всё равно, что перехватить все исключения и игнорировать их.
Это достойное порицания решение, которое может впоследствии привести к тонким ошибкам и недопустимым состояниям программы.

Метод WhenAny возвращает значение типа Task<Task<T>>. Это означает, что по завершении задачи вы получаете объект типа Task<T>.
Он представляет первую из завершившихся задач и поэтому гарантированно находится в состоянии «завершен». Но почему нам возвращают объект Task, а не просто значение типа T?

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

  C#  
Task<Task<Image>> anyTask = Task.WhenAny(tasks);
Task<Image> winner = await anyTask;
Image image = await winner; // Этот оператор всегда завершается синхронно

AddAFavicon(image);
foreach (Task<Image> eachTask in tasks)
{
     if (eachTask != winner)
     {
          await eachTask;
     }
}


Нет ничего предосудительного в том, чтобы обновить пользовательский интерфейс, как только будет получен результат первой завершившейся задачи (winner), но после этого необходимо дождаться остальных задач, как сделано в коде выше. При удачном стечении обстоятельств все они завершатся успешно, и на выполнении программы это никак не отразится. Если же какая-то задача завершится с ошибкой, то вы сможете узнать причину и исправить ошибку.
CancellationToken Отмена асинхронных операций.
Отмена асинхронных операций связывается с типом CancellationToken

По соглашению всякий метод, поддерживающий отмену, должен иметь перегруженный вариант, в котором за обычными параметрами следует параметр типа CancellationToken

  C#  
Task<int> ExecuteNonQueryAsync(CancellationToken cancellationToken)


При вызове метода ThrowIfCancellationRequested отмененного объекта CancellationToken возбуждается исключение типа OperationCanceledException.

  C#  
foreach (var x in thingsToProcess)
{
     cancellationToken.ThrowIfCancellationRequested(); // Обработать x ...
}


Библиотека Task Parallel Library знает, что такое исключение представляет отмену, а не ошибку, и обрабатывает его соответственно. Например, в классе Task имеется свойство IsCanceled, которое автоматически принимает значение true, если при выполнении async-метода произошло исключение OperationCanceledException.

Удобной особенностью подхода к отмене, основанного на маркерах CancellationToken, является тот факт, что один и тот же маркер можно распространить на столько частей асинхронной операции, сколько необходимо, – достаточно просто передать его всем частям.
Неважно, работают они параллельно или последовательно, идет ли речь о медленном вычислении или удаленной операции, – один маркер отменяет всё.
До первого await
До первого await не происходит ничего интересного.
Async не планирует выполнение метода в фоновом потоке. Единственный способ сделать это – воспользоваться методом Task.Run, который специально предназначен для этой цели, или чем-то подобным.

В приложении с пользовательским интерфейсом это означает, что код до первого await работает в потоке пользовательского интерфейса.
А в веб-приложении на базе ASP.NET – в рабочем потоке ASP.NET.

Часто бывает, что выражение в строке, содержащей первый await, содержит еще один async-метод.
Поскольку это выражение предшествует первому await, оно также выполняется в вызывающем потоке.
Таким образом, вызывающий поток продолжает «углубляться» в код приложения, пока не встретит метод, действительно возвращающий объект Task.

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

К счастью, в большинстве случаев он выполняется недолго, но важно помнить, что одно лишь наличие ключевого слова async не гарантирует отзывчивости интерфейса.
Подробнее о классе SynchronizationContext
Текущий контекст SynchronizationContext – это свойство текущего потока. Идея в том, что всякий раз, как код исполняется в каком-то специальном потоке, мы можем получить текущий контекст синхронизации и сохранить его.
Впоследствии этот контекст можно использовать для того, чтобы продолжить исполнение кода в том потоке, в котором оно было начато.

Поэтому нам не нужно точно знать, в каком потоке началось исполнение, достаточно иметь соответствующий объект SynchronizationContext.

В классе SynchronizationContext есть важный метод Post, который гарантирует, что переданный делегат будет исполняться в правильном контексте.
await и SynchronizationContext
Мы знаем, что код, предшествующий первому await, исполняется в вызывающем потоке, но что происходит, когда исполнение вашего метода возобновляется после await?

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

Для достижения такого эффекта используется класс SynchronizationContext.

Важно!!!
В момент приостановки метода при встрече оператора await текущий контекст SynchronizationContext сохраняется.
Далее, когда метод возобновляется, компилятор вставляет вызов Post, чтобы исполнение возобновилось в запомненном контексте.
Взаимодействие с синхронным кодом
В классе Task имеется свойство Result, обращение к которому блокирует вызывающий поток до завершения задачи.

Его можно использовать в тех же местах, что await, но при этом не требуется, чтобы метод был помечен ключевым словом async или возвращал объект Task.
И в этом случае один поток занимается – на этот раз вызывающий (то есть тот, что блокируется).

  C#  
var result = MyMethodAsync().Result;

Исключения в async-методах, возвращающих Task
Большинство написанных вами async-методов возвращают значение типа Task или Task<T>. Цепочка таких методов, в которой каждый ожидает завершения следующего, представляет собой асинхронный аналог стека вызовов в синхронном коде.

Компилятор C# прилагает максимум усилий к тому, чтобы исключения, возбуждаемые в этих методах, вели себя так же, как в синхронном случае. В частности, блок try-catch, окружающий ожидаемый async-метод, перехватывает исключения, возникшие внутри этого метода

  C#  

async Task Catcher()
{
     try
     {
          await Thrower();
     }
     catch (AlexsException)
     {
          // Исключение будет обработано здесь
     }
}

async Task Thrower()
{
     await Task.Delay(100);
     throw new AlexsException();
}


Для этого C# перехватывает все исключения, возникшие в вашем async-методе. Перехваченное исключение помещается в объект Task, который был возвращен вызывающей программе. Объект Task переходит в состояние Faulted. Если задача завершилась с ошибкой, то ожидающий ее метод не возобновится как обычно, а получит исключение, возбужденное в коде внутри await.

В async-методе оно возбуждается там, где находится оператор await, а не в точке фактического вызова метода. Это становится очевидным, если разделить вызов и await.

  C#  

Task task = Thrower();
try
{
     await task;
}
catch (AlexsException)
{
     // Исключение обрабатывается здесь
}
 
← Previous topic
Asynchronous programming in C# (using async, await, and Task as an example)
 
Next topic →
What are Application Domains in C# ? (AppDomain class)
 
Your feedback ... 1 Comments
Михаил
3 June 2022 17:17
"Оно включается в сигнатуру метода точно так же, как, например, слово static."
Мне кажется это не совсем так, ведь сигнатура в интерфейсах не включает в себя async, и все равно работает как надо
   
Your Name
Your comment (www links can only be added by a logged-in user)

 
Download and install Microsoft Visual Studio
Download and install Visual Studio 2026 (for learning C#, writing programs): WPF, ASP.NET, ASP.NET Core, UWP, Maui, Xamarin, Unity, MonoGame)
Download and install Visual Studio 2022 (for learning C#, writing programs): WPF, ASP.NET, ASP.NET Core, UWP, Maui, Xamarin, Unity, MonoGame)
Download and install Visual Studio 2019 (for learning C#, writing programs: WPF, ASP.NET, ASP.NET Core, Xamarin, Unity, MonoGame)
Download and install Visual Studio 2017 (to learn C#, writing programs: WPF, ASP.NET, ASP.NET Core, Xamarin, Unity, MonoGame)
New app for learning C#
Creating a new console application to learn C#
Debugging Code
Debug.Assert(false) Debugging Code in C#
For debugging, option "Common Language Runtime Exceptions" see exceptions when a program is running C#
Attribute [Obsolete("My method is outdated. Do not use", false)] Warning when compiling code in the C#
Data Types C#
C# data types: number (bool, char, byte, int, long, float, double, decimal), text (string), enumeration (enum), class (class), structure (struct)
Structure Boolean in the C# it is a flag with values true or false (bool) and methods for conversion bool
Structure Int32 in the C# it is a signed integer (int) and methods for conversion int
Structure Single in the C# this is a floating-point number (float) and methods for conversion float
var ... Variable of any type in the C#. Example: var str = "Hello!";
Type dynamic in the C#
Default values in the C#
Storing objects in memory. Removing Objects from Memory
Reference types and value types in the C#
Stack (stack) - memory for method parameters and local variables in the C#
Heap - dynamic memory available at run time in the C#
Interface IDisposable. Write code to properly release unmanaged resources in the destructor and in the interface IDisposable in the C#
Memory. Garbage collector (garbage collector). Automatic memory freeing in the C#
C# type conversion
C# converting a string to a number (string → short, int, long, ushort, uint, ulong, float, double, decimal) | Use Culture (system settings)
C# converting a number to a string (int, double, short, ... → string) with the required accuracy
Text in C# (type string and class String)
Algorithm for intersecting rectangles
What is text in the C# ? Type string and class String. Methods for working with text.
Length (string length in C#). Example: string str1 = "Hello"; int v1 = str1.Length;
CompareTo (compares case-sensitive text in C#). Example: bool bIsSame = str1.CompareTo(str2)==0;
ToLower (converts text to lowercase in C#). Example: string str1 = "HELLO World!"; string str2 = str1.ToLower();
ToUpper (converts text to uppercase in C#). Example: string str1 = "Hello World!"; string str2 = str1.ToUpper();
Split (split the string into words in C#). Example: string[] arrWords = strText.Split(" ");
StartsWith (checks the beginning of the text with the specified case-sensitive text in C#). Example: bool bStart = str1.StartsWith(str2);
Contains (checks whether the text specified is case-sensitive or not in case-sensitive C#). Example: bool bFound = str1.Contains(str2);
IndexOf (searches for a case-sensitive string and returns the position in C#). Example: int pos = str1.IndexOf(str2);
Substring (returns part of the text from the specified position and length in the C#). Example: string str1 = "Hello World!"; string str2 = str1.Substring(2, 5);
IsNullOrEmpty (checks the text for blank or for null in the C#). Example: string name = "Hello World!"; bool bFlag = String.IsNullOrEmpty(name);
IsNullOrWhiteSpace (validates text on null or on text with spaces in the C#). Example: string name = "   "; bool bFlag = String.IsNullOrWhiteSpace(name);
[] (returns a character from the specified position in the C#). Example: char symbol = str[1];
Format (text formatting, strings in the C#). Example: string strNew = String.Format("Hello {0}, {1}", name, year);
+ (add lines and text in the C#). Example: string str = str1 + str2 + " people!";
$ (string interpolation in the C#). Example: string result = $"Hello {a} + {b} = {a + b}";
Symbol @ before the beginning of the line in the C#. Example: string str1 = @"aaa";
Use @ and $ together (C# string interpolation)
DateTime in C#
What is DateTime in C# ? Convert to a string with the format
Enumerations in C # (enum)
What is enumeration? (enum) in the C# ?
How to convert text to enum in C#
How to enumerate all elements in enum in C#
null
null value for simple types. Use ? or Nullable in the C#
Operator ?? (null-union) in the C#
try-catch
Exception handling in C#. Operator try catch finally
Classes in C# (class)
What is a class? in the C#?
Class Access Modifiers in the C#. Access modifiers for methods, properties, fields in the C#
"partial class" in the C#. Description of the class in different files
[bgcolor=#F5F9DB]Constructors for a class[/bgcolor]
Class Constructor in the C#
Initializing a Class Object (set values for fields) in the C#
To call the constructor at the base class in the C#
Static constructor in class C#
"base" To call a method from the base class. To call a variable from the base class. To call the constructor from the base class. C#
"this" To set or get a value from a class field. To call the constructor from the class. C#
[bgcolor=#F5F9DB]Class Destructors[/bgcolor]
Class Destructor in the C#
Destructors in classrooms (how basic destructors are called) C#
[bgcolor=#F5F9DB]Inheritance[/bgcolor]
What is class inheritance in C# ?
[bgcolor=#F5F9DB]Inheritance using new[/bgcolor]
Use new for the interface method. Inheriting an interface from an interface with the same method
Use new for the class method. Inheriting a class from a class in C#.
[bgcolor=#F5F9DB]Inheritance using sealed[/bgcolor]
sealed class. Prohibition to inherit in the C#
Inheriting a class from a class in C#. We use words virtual, override, sealed for class methods
[bgcolor=#F5F9DB]Abstract class[/bgcolor]
What is an abstract class? in the C# ? Abstract methods, properties, indexes.
Inheritance from a class abstract in the C#. Use abstract and override for class methods
[bgcolor=#F5F9DB]Constants and readonly [E_M_P_T_Y] fields in the classroom[/bgcolor]
Constants in the classroom C#
readonly . For a class field. This field is read-only in C#
[bgcolor=#F5F9DB]Properties get and set in the classroom C# (accessors)[/bgcolor]
get set Properties in a class C#
Inheritance (virtual, override) for get and set accessors in C#
[bgcolor=#F5F9DB]Operators, indexers in C#[/bgcolor]
Operators in a C# class. Operator overload: > < ++ + true false
Indexers in Class C#
[bgcolor=#F5F9DB]Nested types in C#[/bgcolor]
Nested class, structure in C#
[bgcolor=#F5F9DB]Parameters in the C#[/bgcolor] class method
ref and out (return parameters by reference in the C# method). Example: public void AddValue(ref int value)
Default parameters (optional parameters) in a C# method. Example: public int CalculateSum(int a, int b, int c=7)
C# named parameters. Example: public void CalculateSum(a:7, b:3);
[bgcolor=#F5F9DB]Generic methods, generic classes in C# (templates)[/bgcolor]
A method with generic parameters in C# (templates). Example: public double Sum<T1, T2>(T1 value1, T2 value2) { ... }
A generic (typed) class in C# (templates). Example of a class Book<T> { ... }
where Type constraint in a generic (typed) class in C# (templates). Example of class Dog<T> where T : Cat
[bgcolor=#F5F9DB]Converting a class object from one type to another[/bgcolor]
explicit is an explicit conversion operator in the C class#
implicit is an implicit conversion operator in class C#
Converting a class object from one type to another in C#. Use try( ) is as
Converting a class object from one type to another in C#. Using pattern matching is switch
[bgcolor=#F5F9DB]Class object in C#[/bgcolor]
? conditional null operator in C#
The class object contains a reference in C#
How do you copy objects in C# to copy class data instead of a reference?
[bgcolor=#F5F9DB]Static constructor and static properties and methods[/bgcolor]
Static constructor in class C#
Static methods, properties, members in class C#
[bgcolor=#F5F9DB]Additional class features in C#[/bgcolor]
The extension method in C# (this in the first parameter of the method). Example: static public void AddValues(this List<int> myList, int value1, int value2)
[bgcolor=#F5F9DB]Class naming conventions in C#[/bgcolor]
What letters, lowercase or uppercase, to call classes, methods, properties... in C#
Is it correct to create a separate .cs file for each class in C#? Or write C# classes in a single .cs file?
Static Class
Static Class in C#
Anonymous Class
An object with an anonymous (missing) type in C#. Example: var book = new { BookName = "Lord of the Rings", Price = 100 };
Interfaces
What is interface in C#?
Inheriting the interface from the interface in C#
Inheriting a class from an interface class in C#. Using override and virtual for class methods
Generalized (typed) interface in C# (templates). Example interface IUser<T> { ... }
Struct structure
What is a structure in C#?
Structure access modifiers in C#. Access Modifiers for Methods, Properties, Struct Fields in C#
Initializing a Structure Object (Setting Values for Fields) in C#
How to change the value in an array of structures or in a collection of structures (List) in C#
Nested structure in C#
[bgcolor=#F5F9DB]Converting a struct object from one type to another[/bgcolor]
implicit is an implicit struct-to-C conversion operator#
explicit is an explicit struct-to-C conversion operator#
Lazy class loading in C#
Lazy Object Creation in Memory (class Lazy in C#)
Tuples
Tuples in C#
Dynamic objects with any properties
DynamicObject and ExpandoObject in C#
Arrays
What are arrays? array in C#
Initializing an Array (Populating the Array Elements) in C#
params passing any number of parameters to a method in C#
Array class C#
Collection
What are collections in C#?
What are non-generic collections in C#? ArrayList, Stack, Queue, Hashtable, SortedList, BitArray classes
What are generic (typed) collections in C#? The classes are List<T>, SortedList<T>, Stack<T>, Dictionary<TKey, TValue>, LinkedList<T>, Queue<T>, HashSet<T>, SortedSet<T>, ConcurrentDictionary<TKey, TValue>, SortedDictionary<TKey, TValue>
Non-generic collection classes (different types of items are stored in the same collection)
IEnumerable interface. The most basic interface for collections in C#
Interfaces: ICollection, IList, IDictionary. The basis for collections in C#
ArrayList class (collection in C#)
What is ArrayList in C#?
SortedList class (collection in C#)
What is SortedList in C#?
Stack class (collection in C#)
What is Stack in C# ?
Queue class (collection in C#)
What is Queue in C# ?
Hashtable class (collection in C#)
What is a Hashtable in C# ?
BitArray class (collection in C#)
What is BitArray in C#?
Generic, typed collection classes in C# (elements of the same type are stored in the same collection)
IEnumerable interface<T>. The most basic interface for typed collections in C#
Interfaces: ICollection<T>, IList<T>, ISet<T>, IDictionary<TKey, TValue>. Basis for typed collections in C#
List class<T> (typed collection in C#)
What is List<T> in C#?
Initializing the Collection List in curly brackets in the C#
for, foreach (go through all the items in the List<T>) in C#
Find (looking for an item by criterion in the List<T>) in C#
FindAll (looking for a list of items by criterion in the List<T>) in C#
ForEach (for each List element an<T> action is performed) in C#
LinkedList class<T> (typed collection in C#)
What is LinkedList<T> in C# ?
SortedList<TKey, TValue> class (typed collection in C#)
What is SortedList<TKey, TValue> in C# ?
Stack class<T> (typed collection in C#)
What is Stack<T> in C# ?
Queue class<T> (typed collection in C#)
What is Queue<T> in C# ?
HashSet class<T> (typed collection in C#)
What is a HashSet<T> in C# ?
How HashSet works<T> in C#
SortedSet class<T> (typed collection in C#)
What is a SortedSet<T> in C#?
ObservableCollection class<T> (typed collection in C#)
What is ObservableCollection<T> in C#?
Dictionary<TKey, TValue> class (typed collection in C#)
What is Dictionary<TKey, TValue> in C# ?
Initializing Elements in the Dictionary<TKey, TValue> Constructor in C#
How Dictionary<TKey, TValue> works in C#
How to convert IEnumerable to → Dictionary in C#<TKey, TValue> . Using the ToDictionary method
SortedDictionary<TKey, TValue> class (typed collection in C#)
What is SortedDictionary<TKey, TValue> in C# ?
ConcurrentDictionary<TKey, TValue> class (typed collection in C#)
What is ConcurrentDictionary<TKey, TValue> in C# ?
AddOrUpdate (add or update a value by key in ConcurrentDictionary<TKey, TValue>) in C#
Asymptotic complexity for adding, removing, taking an item in collections
Asymptotic complexity for adding, removing, taking an element in collections C# (List, SortedList, Stack, Dictionary, LinkedList, Queue, HashSet, SortedSet, ConcurrentDictionary, SortedDictionary)
Sorting Elements in the [] Array and List <T>Collection
Sorting elements in the [] array and List collection<T> in C#. IComparable interface
Sorting elements in the [] array and List collection<T> in C#. IComparer interface
My implementation of IEnumerator, IEnumerable, and iterators
Example: My implementation of the IEnumerable and IEnumerator interfaces in C#
Iterators and yield in C#. Examples of IEnumerable implementation with yield
Extension Methods for IEnumerable<T> (Search, Replace, Value Sampling) in C#
Methods for finding, replacing, and fetching values in IEnumerable<T>. Extension methods for IEnumerable<T> in C#
Any (IEnumerable extension method<T>) in C#
Select (IEnumerable extension method<T>) in C#
GroupBy (extension method IEnumerable<T>) in the C#
GroupJoin (extension method IEnumerable<T>) in the C#
Sorting, filtering in LINQ (Language-Integrated Query)
What is LINQ in C#?
Sorting, filtering list items using LINQ in C#
Books for learning LINQ in C#
Pointers
Pointers in C#. Operator unsafe
Pointers to structs, class fields, arrays in C#. Operators unsafe, stackalloc, fixed
Working with files
Open the file, read the text from the file and break it down by words. C#
Create a text file, write the text to a C file#
Create an HTML file, write tabular data in an HTML file | C#
Create a binary file, write bytes to file C#
Partial upload of a file from FTP to C#
Class Path. Combine method - merges the strings into the full path of the file. And other methods of the Path class | C#
Serialization
What is object serialization in C#? [Serializable] attribute
Serializing a C# object into a binary file. BinaryFormatter class. [Serializable] attribute
Serializing a C# object into an XML file. XmlSerializer class. [Serializable] attribute
Serialization of a C# object into a JSON file. DataContractJsonSerializer class. [Serializable] attribute
Serializing a C# object into a SOAP file. SoapFormatter class. [Serializable] attribute
Namespaces
Namespace using in C#
Delegate
Delegate in C#
Add method(s) in a C# delegate. Unification of delegates. Removing a Method from a Delegate
Delegate as a parameter in method C#
Unnamed, anonymous method in C# (method described in place of parameter, delegate)
Universal Delegates
Generic, generic delegates in C# (templates)
Action, Predicate, and Func Universal Delegates in C#
Events
Events in C#
Lyamda
Lamda (example) in C#
Regular expressions
Regular Expressions in C#
Breaking the text into words (regular expressions in c#)
Put * instead of the last name after the first letter (regular expressions in c#)
Breaking the text into words (regular expressions in c#)
Process, process modules
Process in C# (Process class)
Process modules in C# (ProcessModule class)
Threads, multithreading
Threads in C# (Thread class)
Thread Pool in C#
What"s the difference between background and foreground in C#?
Synchronizing Threads in C#
Parallel Library Task (TPL)
Parallel Library Task (TPL). Parallel Task Library in C#
The Parallel class uses the Invoke method to execute the for and foreach (on different CPU cores) methods in parallel in C#
PLINQ parallelizes LINQ queries to run on different processor cores in C#
Asynchronous methods (async and await)
class Task in C#
Asynchronous programming in C# (async, await how to formalize)
Asynchronous programming in C# (using async, await, and Task as an example)
Asynchronous Programming in C# (Theory)
Application domains
What are Application Domains in C# ? (AppDomain class)
Example "Application domain information" (current domain name, list assemblies) in C#
Example "Let"s create the 2nd application domain. Write the class in the 1st domain and use it in the 2nd domain. MarshalByRefObject in C#
Example "Load the 2nd domain of the application from a file, run the calculations, unload the 2nd domain from memory" to C#
Attributes
Attributes for Class, Method, Property in C#
Attribute [Conditional("AAA")] . For compilation, ignore a method or property unless a conditional compilation symbol is defined in C#
Attribute [Obsolete("My method is outdated. Do not use", false)] Warning when compiling code in the C#
The [Display(Name="Sleep at night")] attribute. To store some text attached to a variable | C#
The attribute [Required(ErrorMessage = "Please enter a name")] is described for a property in the C# class and requires the property to be populated if the ErrorMessage error in the MVC ASP.NET is not filled in the screen
The attribute [Remote("IsValidAuthor", "Home", ErrorMessage = "Enter correct author of book")] is described for a property in a C# class and checks that property for correctness on the server via the IsValidAuthor method in conroller Home, if the method returns false, then there will be an ErrorMessage error on the screen in the MVC ASP.NET
Reflection in C#
Nameof operator in C# (class name, method name, variable name)
What is reflection in C#? Type Class
Creating a class object and calling the constructor with parameters using reflection in C#
How to get attribute information for a method from a class. Using reflection | C#
How to get attribute information for a property of a class. Using reflection | C#
How to change the set property in a class if private using reflection | C#
Preprocessor directives (if on compilation)
#define #undef #if #elif #else #endif preprocessor directives in C#
How do I define #define for all files (for the entire project) in C#?
What is the CLR assembly and runtime?
Assembly (Assembly) in C#. Compilation. Intermediate code IL (Intermediate Language). Metadata.
How to include a C# assembly in a project?
Utility ildasm.exe. Converts an assembly (C# exe, dll file) to an intermediate language (IL). This utility is easy to learn
The runtime CLR (Common Language Runtime) in C# . JIT (Just-In-Time) compiler.
Creating and connecting our build
Creating our C# build (regular build)
Connecting our C# build (regular build)
Creating our C# assembly (split assembly)
Connecting our C# assembly (split assembly)
Database in Console Application C#
Entity Framework in a C# console application. Using Code First (we write c# code, and the tables in the database are created by ourselves)
Read the image from the database and save it to a file | ADO.NET, C#, console application
DI Dependency Injection in C#
Dependency injection in C# | Dependency Injection (DI)
Ninject (IoC container) dependency management in C#
Autofac (IoC container) dependency management in C#
Convenient Visual Studio utilities
View Class Diagram in C#
exe to C# code
"dotPeek" application for decompile (disassemble) exe to c# source code
In a C# application, call the C++ functions
What are managed code (managed code) and unmanaged code (unmanaged code)? | C# and C++
Marshaling (marshalling) in C#. Type Conversion Between Managed Code (managed code) and Unmanaged Code (unmanaged code)
In the application C# we call functions from Windows dll (C++ WinAPI). Attribute [DllImport("user32.dll")]
In a C# application, call functions from my dll (C++). Attribute [DllImport("My.dll", CallingConvention = CallingConvention.Cdecl)]
Additional topics, questions
You don"t create a new project in Visual Studio 2019. Object reference not set to instance of an object"
C# compilation error: error CS1106: Extension method must be defined in a non-generic static class
C# compilation error: error CS0246: The type or namespace name "Point" could not be found (are you missing a using directive or an assembly reference?)
Why can"t the Dictionary.TryGetValue method find a value by key in C#?
Object-oriented programming (OOP). OOP Principles: Abstraction, Encapsulation, Inheritance, Polymorphism
What letters in C# (uppercase or lowercase or uppercase) should we use to name fields, methods in a class, interfaces, delegates, parameters?
Is it correct to create a separate .cs file for each class in C#? Or write C# classes in a single .cs file?
Is it better to use a built-in int type or an Integer class (string type or String class) in C#?
How do I download and install the version of the .NET Framework I want in Visual Studio?
Boxing and unboxing meaningful types in C#
Error CS8107 Feature "default literal" is not available in C# 7.0. Please use language version 7.1 or greater
Error "unable to connect to web server "iis express" | C# | Visual Studio 2017
Uninstall and install NuGet in Visual Studio
When opening a project in Visual Studio 2019 error: "project requires "SQL Server 2012 Express LocalDB" which is not installed on this computer"
The checked and unchecked math operators
The unchecked math operator in C#
The checked math operator in C#
Additional C# classes
C# Random class
C# Structure Point
C# PointF structure
C# Size structure
C# SizeF structure
C# Rectangle Structure
C# RectangleF structure
It"s time
The amount of time that has elapsed since the system booted (in milliseconds). System.Environment.TickCount in C#
Encryption
Let"s encrypt the password and check it | C# console application
Excell
Reading an excel file in C# (console application)
WWW Sites to Learn C#
Websites to learn C#

  Ваши вопросы присылайте по почте: info@dir.by