Обложка канала

.NET Разработчик

Опытный разработчик не так давно зашёл в .Net и поставил цель получить сертификат Microsoft. Свой ежедневный прогресс он описывает на канале .Net Разработчик. Заметки об изученном материале, советы по повышению производительности и поддержке мотивации, ин

.NET Разработчик

4 года назад
Открыть в
День 1390. #ЗаметкиНаПолях #AsyncTips Блокировки с async Задача Имеются общие данные. Требуется обеспечить безопасное чтение и запись этих данных из разных блоков кода, внутри которых может использоваться await. Решение Тип SemaphoreSlim был обновлён в .NET 4.5 для обеспечения совместимости с async. Пример использования:
class MyClass
{
  private int _value;
  // Блокировка защищает поле _value
  private readonly SemaphoreSlim
    semaphore = new SemaphoreSlim(1);

  public async Task IncAsync(string name)
  {
    await semaphore.WaitAsync();
    try
    {
      int oldValue = _value;
      await Task.Delay(1000 * oldValue);
      _value = oldValue + 1;

      Console.WriteLine($"{name}: {_value}");
    }
    finally
    {
      semaphore.Release();
    }
  }
}

Тестовый вариант использования класса:
var cls = new MyClass();

for (int i = 1; i <= 5; i++)
{
  int count = i;
  Thread t = new(
    async () => 
     await cls.IncAsync("Поток " + count)
  );
  t.Start();
}
Console.ReadLine();

Этот код будет выводить одну за другой строки с постоянно увеличивающейся задержкой между ними:
Поток 4: 1
Поток 3: 2
Поток 2: 3
Поток 5: 4
Поток 1: 5

Заметьте, что SemaphoreSlim принимает в качестве параметра конструктора количество потоков, которые одновременно могут получить доступ к блокировке. В данном случае мы задали 1. В этой ситуации действуют рекомендации из предыдущего совета: Экземпляры блокировок должны быть приватными; т.е. не должны быть доступными за пределами класса. Обязательно чётко документируйте (и тщательно продумывайте), что именно защищает экземпляр блокировки. Сведите к минимуму объём кода, выполняемого при удержании блокировки. В частности, не вызывайте произвольный код, включая выдачу событий, вызов виртуальных методов и вызов делегатов. Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 12.