任务限制不适用于ConcurrentExclusiveSchedulerPair

时间:2019-01-14 17:04:05

标签: c# .net asynchronous async-await throttling

我正在尝试限制提交给外部数据库服务器的异步任务的数量。我创建了以下测试代码,执行该测试代码需要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 :(得分:0)

  

我正在尝试限制提交给外部数据库服务器的异步任务的数量。

TaskScheduler只能用于控制运行任务的数量。异步任务不会“运行”。它们可以处于“进行中”状态,但实际上并不是运行代码。换句话说,TaskScheduler仅适用于同步任务。或者,如果您想使用this terminology,则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(); }
  }
}