Регулирование задач не работает с ConcurrentExclusiveSchedulerPair - PullRequest
0 голосов
/ 14 января 2019

Я пытаюсь ограничить число асинхронных задач, которые я отправляю на внешний сервер базы данных. Я создал следующий тестовый код, выполнение которого должно занять 25 секунд (150 задач * 5 секунд / 30 макс. Одновременных задач = 25 секунд).

    private async void ThrottlingTest()
    {
        TaskScheduler scheduler = new ConcurrentExclusiveSchedulerPair(TaskScheduler.Default, 30).ConcurrentScheduler;
        Stopwatch sw = new Stopwatch();

        int numTasks = 150;
        Task[] tasks = new Task[numTasks];

        for (int i = 0; i < numTasks; i++)
        {
            tasks[i] = Task.Factory.StartNew(() => Task.Delay(5000), CancellationToken.None, TaskCreationOptions.None, scheduler).Unwrap();
        }

        sw.Start();
        await Task.WhenAll(tasks);
        sw.Stop();
        long duration = sw.ElapsedMilliseconds;
    }

Однако выполнение этого кода занимает всего 5 секунд, указывая, что мое регулирование не работает. Что я делаю неправильно? Я подозреваю, что Task.Delay работает с использованием планировщика по умолчанию. Если да, то с каким механизмом задержки я могу проверить?

1 Ответ

0 голосов
/ 31 января 2019

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

TaskScheduler s может использоваться только для управления количеством запущенных задач. Асинхронные задачи не «запускаются». Они могут быть «в процессе», но на самом деле они не исполняют код , хотя и так. Другими словами, TaskScheduler s работает только так, как ожидается с синхронными задачами. Или, если вы хотите использовать , эта терминология , TaskScheduler была разработана для задач делегатов; они не понимают Задач Обещания.

Чтобы ограничить асинхронные операции, используйте SemaphoreSlim вместо:

private async void ThrottlingTest()
{
  SemaphoreSlim mutex = new SemaphoreSlim(30);
  Stopwatch sw = new Stopwatch();

  int numTasks = 150;
  Task[] tasks = new Task[numTasks];
  for (int i = 0; i < numTasks; i++)
    tasks[i] = TestAsync();

  sw.Start();
  await Task.WhenAll(tasks);
  sw.Stop();
  long duration = sw.ElapsedMilliseconds;

  async Task TestAsync()
  {
    await mutex.WaitAsync();
    try { await Task.Delay(5000); }
    finally { mutex.Release(); }
  }
}
...