我正在尝试限制提交给外部数据库服务器的异步任务的数量。我创建了以下测试代码,执行该测试代码需要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正在使用默认调度程序运行。如果可以,我可以使用哪种延迟机制进行测试?
答案 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(); }
}
}