Подтвердить что ты не робот

Необходимо понимать использование SemaphoreSlim

Вот код, который у меня есть, но я не понимаю, что делает СемафорСлим.

async Task WorkerMainAsync()
{
  SemaphoreSlim ss = new SemaphoreSlim(10);
  List<Task> trackedTasks = new List<Task>();
  while (DoMore())
  {
    await ss.WaitAsync();
    trackedTasks.Add(Task.Run(() =>
              {
                DoPollingThenWorkAsync();
                ss.Release();
              }));
  }
  await Task.WhenAll(trackedTasks);
}

void DoPollingThenWorkAsync()
{
  var msg = Poll();
  if (msg != null)
  {
    Thread.Sleep(2000); // process the long running CPU-bound job
  }
}

Что ждет ss.WaitAsync(); & ss.Release(); do?

Я предполагаю, что если я запускаю 50 потоков за раз, тогда пишу код типа SemaphoreSlim ss = new SemaphoreSlim(10);, тогда он будет вынужден запускать 10 активных потоков во время.

Когда один из 10 потоков завершится, начнется другой поток... если я не прав, помогите мне разобраться с ситуацией с образцом.

Почему нужно использовать вместе с ss.WaitAsync();? Что делает ss.WaitAsync();?

4b9b3361

Ответ 1

Я предполагаю, что если я запускаю 50 потоков за один раз, тогда код типа SemaphoreSlim ss = new SemaphoreSlim (10); заставит запустить 10 активных потоков во время

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

Вызов WaitAsync на семафоре создает задачу, которая будет завершена, когда этому потоку будет предоставлен "доступ" к этому токену. await - эта задача позволяет программе продолжить выполнение, когда это разрешено. Наличие асинхронной версии, а не вызова Wait важно, чтобы гарантировать, что метод остается асинхронным, а не синхронным, а также имеет дело с тем, что метод async может выполнять код через несколько потоков, к обратным вызовам, и поэтому сродство естественной нити с семафорами может быть проблемой.

Примечание: DoPollingThenWorkAsync не должен иметь постфикс async, потому что он фактически не асинхронный, он синхронный. Просто назовите его DoPollingThenWork. Это уменьшит путаницу для читателей.

Ответ 2

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

http://www.tomdupont.net/2016/03/how-to-release-semaphore-with-using.html

Я _isDisposed=true местами _isDisposed=true и _semaphore.Release() вокруг его Dispose, хотя в случае, если он как-то вызывался несколько раз.

Также важно отметить, что SemaphoreSlim не является блокировкой повторного входа, то есть если один и тот же поток вызывает WaitAsync несколько раз, то счетчик, который имеет семафор, уменьшается каждый раз. Короче говоря, SemaphoreSlim не поддерживает темы.

Что касается качества кода вопросов, то лучше сделать окончательную версию Release, чтобы убедиться, что она всегда будет выпущена.