Чтобы обеспечить функциональность производителя-потребителя, которая может ставить в очередь и выполнять asyn c методы один за другим, я пытаюсь реализовать очередь asyn c. Я заметил серьезные проблемы с производительностью, используя его в большом приложении.
async Task Loop() {
while (Verify()) {
if (!_blockingCollection.TryTake(out var func, 1000, _token)) continue;
await func.Invoke();
}
}
Реализация AsyncQueue.Add:
public void Add(Func<Task> func) {
_blockingCollection.Add(func);
}
Пример использования из произвольного потока:
controller.OnEvent += (o, a) => _queue.Add(async (t) => await handle(a));
Пути выполнения зависят от состояния приложения и включают
asyn c сетевые запросы, которые внутренне используют TaskCompletionSource для возврата результата
Операции ввода-вывода
задачи, которые добавляются в список и ожидаются с помощью Task.WhenAll (...)
asyn c void метод, который преобразует массив и ожидает сетевого запроса
Симптомы: приложение постепенно замедляется.
Когда я заменяю await func.Invoke()
на func.Invoke().Wait()
вместо ожидания это правильно, производительность резко улучшается и не тормозит.
Почему так? Является ли очередь asyn c, использующая BlockingCollection
, плохой идеей?
Какая альтернатива лучше?